Skip to content

Commit b3969d3

Browse files
committed
Merge branch 'feat/ipv6-address-converter' into chore/all-my-stuffs
# Conflicts: # package.json # pnpm-lock.yaml # src/tools/index.ts # src/tools/integer-base-converter/integer-base-converter.model.test.ts # src/tools/integer-base-converter/integer-base-converter.model.ts # src/utils/ip.test.ts
2 parents 86feffa + e56eee9 commit b3969d3

File tree

8 files changed

+229
-5
lines changed

8 files changed

+229
-5
lines changed

src/tools/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ import { tool as htmlToMarkdown } from './html-to-markdown';
208208
import { tool as pdfUnlock } from './pdf-unlock';
209209
import { tool as ipCidrToRange } from './ip-cidr-to-range';
210210
import { tool as ipRangeToCidr } from './ip-range-to-cidr';
211+
import { tool as ipv6AddressConverter } from './ipv6-address-converter';
211212

212213
export const toolsByCategory: ToolCategory[] = [
213214
{
@@ -407,6 +408,7 @@ export const toolsByCategory: ToolCategory[] = [
407408
ipv4AddressConverter,
408409
// ipv6AddressConverter,
409410
ipInRange,
411+
ipv6AddressConverter,
410412
ipv4RangeExpander,
411413
macAddressLookup,
412414
macAddressGenerator,

src/tools/integer-base-converter/integer-base-converter.model.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ describe('integer-base-converter', () => {
2626
expect(convertBase({ value: '0b10101010', fromBase: -1, toBase: 10 })).toEqual('170');
2727
expect(convertBase({ value: '0b_1010_1010', fromBase: -1, toBase: 10 })).toEqual('170');
2828
expect(convertBase({ value: '192,654', fromBase: 10, toBase: 8 })).toEqual('570216');
29+
expect(convertBase({ value: '42540766411283223938465490632011909384', fromBase: 10, toBase: 10 })).toEqual('42540766411283223938465490632011909384');
30+
expect(convertBase({ value: '42540766411283223938465490632011909384', fromBase: 10, toBase: 16 })).toEqual('20010db8000085a300000000ac1f8908');
31+
expect(convertBase({ value: '20010db8000085a300000000ac1f8908', fromBase: 16, toBase: 10 })).toEqual('42540766411283223938465490632011909384');
2932
});
3033
});
3134
});

src/tools/integer-base-converter/integer-base-converter.model.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,16 @@ export function convertBase(
4646
let decValue = cleanedValue
4747
.split('')
4848
.reverse()
49-
.reduce((carry: number, digit: string, index: number) => {
49+
.reduce((carry: bigint, digit: string, index: number) => {
5050
if (!fromRange.includes(digit)) {
5151
throw new Error(`Invalid digit "${digit}" for base ${finalFromBase}.`);
5252
}
53-
return (carry += fromRange.indexOf(digit) * finalFromBase ** index);
54-
}, 0);
53+
return (carry += BigInt(fromRange.indexOf(digit)) * BigInt(fromBase) ** BigInt(index));
54+
}, 0n);
5555
let newValue = '';
5656
while (decValue > 0) {
57-
newValue = toRange[decValue % toBase] + newValue;
58-
decValue = (decValue - (decValue % toBase)) / toBase;
57+
newValue = toRange[Number(decValue % BigInt(toBase))] + newValue;
58+
decValue = (decValue - (decValue % BigInt(toBase))) / BigInt(toBase);
5959
}
6060
return newValue || '0';
6161
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
declare module 'cidr-tools' {
2+
type IPv4Address = string;
3+
type IPv4CIDR = string;
4+
type IPv6Address = string;
5+
type IPv6CIDR = string;
6+
7+
type Network = IPv4Address | IPv4CIDR | IPv6Address | IPv6CIDR;
8+
type Networks = Network | Network[];
9+
10+
type Parsed = {
11+
cidr: string;
12+
version: number;
13+
prefix: string;
14+
start: bigint;
15+
end: bigint;
16+
single: boolean;
17+
ip: string;
18+
};
19+
20+
type NormalizeOpts = {
21+
compress?: boolean;
22+
hexify?: boolean;
23+
};
24+
25+
export function merge(networks: Networks): Network[];
26+
export function exclude(baseNetworks: Networks, excludeNetworks: Networks): Network[];
27+
export function expand(networks: Networks): Network[];
28+
export function overlap(networksA: Networks, networksB: Networks): boolean;
29+
export function normalize(cidr: Networks, opts?: NormalizeOpts): Networks;
30+
export function contains(networksA: Networks, networksB: Networks): boolean;
31+
export function parse(network: Network): Parsed;
32+
33+
declare const _default: {
34+
merge: typeof merge;
35+
exclude: typeof exclude;
36+
expand: typeof expand;
37+
overlap: typeof overlap;
38+
normalize: typeof normalize;
39+
contains: typeof contains;
40+
parse: typeof parse;
41+
};
42+
export default _default;
43+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Binary } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'Ipv6 address converter',
6+
path: '/ipv6-address-converter',
7+
description: 'Convert an ip address into decimal, binary, hexadecimal and get infos',
8+
keywords: ['ipv6', 'address', 'converter', 'decimal', 'hexadecimal', 'binary', 'ipv4'],
9+
component: () => import('./ipv6-address-converter.vue'),
10+
icon: Binary,
11+
createdAt: new Date('2024-01-10'),
12+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
declare module 'ip-bigint' {
2+
type IPInfo = {
3+
number: bigint;
4+
version: number;
5+
ipv4mapped?: boolean;
6+
scopeid?:string;
7+
};
8+
type StringifyOptions = {
9+
compress?:boolean;
10+
hexify?:boolean;
11+
};
12+
13+
export function normalizeIp(ip: string, options: StringifyOptions = {compress = true, hexify = false} = {})
14+
export function stringifyIp(ip: IPInfo, options: StringifyOptions = {compress = true, hexify = false}): string;
15+
export function ipVersion(ip: string): number;
16+
export function parseIp(ip): IPInfo;
17+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<script setup lang="ts">
2+
import { isIPv6 } from 'is-ip';
3+
import { parse } from 'cidr-tools';
4+
import { stringifyIp } from 'ip-bigint';
5+
import { convertBase } from '../integer-base-converter/integer-base-converter.model';
6+
import { getIPNetworkType, toARPA, toMicrosoftTranscription } from '@/utils/ip';
7+
import { useValidation } from '@/composable/validation';
8+
9+
const rawIpAddress = useStorage('ipv6-converter:ip', '2001:db8:0:85a3::ac1f:8001'); // NOSONAR
10+
11+
const convertedSections = computed(() => {
12+
try {
13+
const parsedIPv6 = parse(rawIpAddress.value);
14+
const ipInDecimal = parsedIPv6.start;
15+
16+
return [
17+
{
18+
label: 'Decimal: ',
19+
value: String(ipInDecimal),
20+
},
21+
{
22+
label: 'Hexadecimal: ',
23+
value: convertBase({ fromBase: 10, toBase: 16, value: String(ipInDecimal) }).toUpperCase(),
24+
},
25+
{
26+
label: 'Binary: ',
27+
value: convertBase({ fromBase: 10, toBase: 2, value: String(ipInDecimal) }),
28+
},
29+
{
30+
label: 'CIDR: ',
31+
value: parsedIPv6.cidr,
32+
},
33+
{
34+
label: 'Ipv6 (short): ',
35+
value: stringifyIp({ number: ipInDecimal, version: 6 }, { compress: true }),
36+
},
37+
{
38+
label: 'Ipv6 (long): ',
39+
value: stringifyIp({ number: ipInDecimal, version: 6 }, { compress: false }),
40+
},
41+
{
42+
label: 'ARPA: ',
43+
value: toARPA(parsedIPv6.ip),
44+
},
45+
{
46+
label: 'Microsoft Transcription: ',
47+
value: toMicrosoftTranscription(parsedIPv6.ip),
48+
},
49+
{
50+
label: 'Type: ',
51+
value: getIPNetworkType(parsedIPv6.ip),
52+
},
53+
];
54+
}
55+
catch (e) {
56+
return [];
57+
}
58+
});
59+
60+
const { attrs: validationAttrs } = useValidation({
61+
source: rawIpAddress,
62+
rules: [{ message: 'Invalid ipv6 address', validator: ip => isIPv6(ip) }],
63+
});
64+
</script>
65+
66+
<template>
67+
<div>
68+
<c-input-text v-model:value="rawIpAddress" label="The ipv6 address:" placeholder="The ipv6 address..." />
69+
70+
<n-divider />
71+
72+
<input-copyable
73+
v-for="{ label, value } of convertedSections"
74+
:key="label"
75+
:label="label"
76+
label-position="left"
77+
label-width="100px"
78+
label-align="right"
79+
mb-2
80+
:value="validationAttrs.validationStatus === 'error' ? '' : value"
81+
placeholder="Set a correct ipv6 address"
82+
/>
83+
</div>
84+
</template>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
declare module 'is-ip' {
2+
3+
/**
4+
Check if `string` is IPv6 or IPv4.
5+
6+
@example
7+
```
8+
import {isIP} from 'is-ip';
9+
10+
isIP('1:2:3:4:5:6:7:8');
11+
//=> true
12+
13+
isIP('192.168.0.1');
14+
//=> true
15+
```
16+
*/
17+
export function isIP(string: string): boolean; // eslint-disable-line @typescript-eslint/naming-convention
18+
19+
/**
20+
Check if `string` is IPv6.
21+
22+
@example
23+
```
24+
import {isIPv6} from 'is-ip';
25+
26+
isIPv6('1:2:3:4:5:6:7:8');
27+
//=> true
28+
```
29+
*/
30+
export function isIPv6(string: string): boolean; // eslint-disable-line @typescript-eslint/naming-convention
31+
32+
/**
33+
Check if `string` is IPv4.
34+
35+
@example
36+
```
37+
import {isIPv4} from 'is-ip';
38+
39+
isIPv4('192.168.0.1');
40+
//=> true
41+
```
42+
*/
43+
export function isIPv4(string: string): boolean; // eslint-disable-line @typescript-eslint/naming-convention
44+
45+
/**
46+
@returns `6` if `string` is IPv6, `4` if `string` is IPv4, or `undefined` if `string` is neither.
47+
48+
@example
49+
```
50+
import {ipVersion} from 'is-ip';
51+
52+
ipVersion('1:2:3:4:5:6:7:8');
53+
//=> 6
54+
55+
ipVersion('192.168.0.1');
56+
//=> 4
57+
58+
ipVersion('abc');
59+
//=> undefined
60+
```
61+
*/
62+
export function ipVersion(string: string): 6 | 4 | undefined;
63+
}

0 commit comments

Comments
 (0)