source: frontend/node_modules/@leichtgewicht/ip-codec/index.mjs

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 5.9 KB
Line 
1const v4Regex = /^(\d{1,3}\.){3,3}\d{1,3}$/
2const v4Size = 4
3const v6Regex = /^(::)?(((\d{1,3}\.){3}(\d{1,3}){1})?([0-9a-f]){0,4}:{0,2}){1,8}(::)?$/i
4const v6Size = 16
5
6export const v4 = {
7 name: 'v4',
8 size: v4Size,
9 isFormat: ip => v4Regex.test(ip),
10 encode (ip, buff, offset) {
11 offset = ~~offset
12 buff = buff || new Uint8Array(offset + v4Size)
13 const max = ip.length
14 let n = 0
15 for (let i = 0; i < max;) {
16 const c = ip.charCodeAt(i++)
17 if (c === 46) { // "."
18 buff[offset++] = n
19 n = 0
20 } else {
21 n = n * 10 + (c - 48)
22 }
23 }
24 buff[offset] = n
25 return buff
26 },
27 decode (buff, offset) {
28 offset = ~~offset
29 return `${buff[offset++]}.${buff[offset++]}.${buff[offset++]}.${buff[offset]}`
30 }
31}
32
33export const v6 = {
34 name: 'v6',
35 size: v6Size,
36 isFormat: ip => ip.length > 0 && v6Regex.test(ip),
37 encode (ip, buff, offset) {
38 offset = ~~offset
39 let end = offset + v6Size
40 let fill = -1
41 let hexN = 0
42 let decN = 0
43 let prevColon = true
44 let useDec = false
45 buff = buff || new Uint8Array(offset + v6Size)
46 // Note: This algorithm needs to check if the offset
47 // could exceed the buffer boundaries as it supports
48 // non-standard compliant encodings that may go beyond
49 // the boundary limits. if (offset < end) checks should
50 // not be necessary...
51 for (let i = 0; i < ip.length; i++) {
52 let c = ip.charCodeAt(i)
53 if (c === 58) { // :
54 if (prevColon) {
55 if (fill !== -1) {
56 // Not Standard! (standard doesn't allow multiple ::)
57 // We need to treat
58 if (offset < end) buff[offset] = 0
59 if (offset < end - 1) buff[offset + 1] = 0
60 offset += 2
61 } else if (offset < end) {
62 // :: in the middle
63 fill = offset
64 }
65 } else {
66 // : ends the previous number
67 if (useDec === true) {
68 // Non-standard! (ipv4 should be at end only)
69 // A ipv4 address should not be found anywhere else but at
70 // the end. This codec also support putting characters
71 // after the ipv4 address..
72 if (offset < end) buff[offset] = decN
73 offset++
74 } else {
75 if (offset < end) buff[offset] = hexN >> 8
76 if (offset < end - 1) buff[offset + 1] = hexN & 0xff
77 offset += 2
78 }
79 hexN = 0
80 decN = 0
81 }
82 prevColon = true
83 useDec = false
84 } else if (c === 46) { // . indicates IPV4 notation
85 if (offset < end) buff[offset] = decN
86 offset++
87 decN = 0
88 hexN = 0
89 prevColon = false
90 useDec = true
91 } else {
92 prevColon = false
93 if (c >= 97) {
94 c -= 87 // a-f ... 97~102 -87 => 10~15
95 } else if (c >= 65) {
96 c -= 55 // A-F ... 65~70 -55 => 10~15
97 } else {
98 c -= 48 // 0-9 ... starting from charCode 48
99 decN = decN * 10 + c
100 }
101 // We don't know yet if its a dec or hex number
102 hexN = (hexN << 4) + c
103 }
104 }
105 if (prevColon === false) {
106 // Commiting last number
107 if (useDec === true) {
108 if (offset < end) buff[offset] = decN
109 offset++
110 } else {
111 if (offset < end) buff[offset] = hexN >> 8
112 if (offset < end - 1) buff[offset + 1] = hexN & 0xff
113 offset += 2
114 }
115 } else if (fill === 0) {
116 // Not Standard! (standard doesn't allow multiple ::)
117 // This means that a : was found at the start AND end which means the
118 // end needs to be treated as 0 entry...
119 if (offset < end) buff[offset] = 0
120 if (offset < end - 1) buff[offset + 1] = 0
121 offset += 2
122 } else if (fill !== -1) {
123 // Non-standard! (standard doens't allow multiple ::)
124 // Here we find that there has been a :: somewhere in the middle
125 // and the end. To treat the end with priority we need to move all
126 // written data two bytes to the right.
127 offset += 2
128 for (let i = Math.min(offset - 1, end - 1); i >= fill + 2; i--) {
129 buff[i] = buff[i - 2]
130 }
131 buff[fill] = 0
132 buff[fill + 1] = 0
133 fill = offset
134 }
135 if (fill !== offset && fill !== -1) {
136 // Move the written numbers to the end while filling the everything
137 // "fill" to the bytes with zeros.
138 if (offset > end - 2) {
139 // Non Standard support, when the cursor exceeds bounds.
140 offset = end - 2
141 }
142 while (end > fill) {
143 buff[--end] = offset < end && offset > fill ? buff[--offset] : 0
144 }
145 } else {
146 // Fill the rest with zeros
147 while (offset < end) {
148 buff[offset++] = 0
149 }
150 }
151 return buff
152 },
153 decode (buff, offset) {
154 offset = ~~offset
155 let result = ''
156 for (let i = 0; i < v6Size; i += 2) {
157 if (i !== 0) {
158 result += ':'
159 }
160 result += (buff[offset + i] << 8 | buff[offset + i + 1]).toString(16)
161 }
162 return result
163 .replace(/(^|:)0(:0)*:0(:|$)/, '$1::$3')
164 .replace(/:{3,4}/, '::')
165 }
166}
167
168export const name = 'ip'
169export function sizeOf (ip) {
170 if (v4.isFormat(ip)) return v4.size
171 if (v6.isFormat(ip)) return v6.size
172 throw Error(`Invalid ip address: ${ip}`)
173}
174
175export function familyOf (string) {
176 return sizeOf(string) === v4.size ? 1 : 2
177}
178
179export function encode (ip, buff, offset) {
180 offset = ~~offset
181 const size = sizeOf(ip)
182 if (typeof buff === 'function') {
183 buff = buff(offset + size)
184 }
185 if (size === v4.size) {
186 return v4.encode(ip, buff, offset)
187 }
188 return v6.encode(ip, buff, offset)
189}
190
191export function decode (buff, offset, length) {
192 offset = ~~offset
193 length = length || (buff.length - offset)
194 if (length === v4.size) {
195 return v4.decode(buff, offset, length)
196 }
197 if (length === v6.size) {
198 return v6.decode(buff, offset, length)
199 }
200 throw Error(`Invalid buffer size needs to be ${v4.size} for v4 or ${v6.size} for v6.`)
201}
Note: See TracBrowser for help on using the repository browser.