Skip to content

Commit

Permalink
Add an IPv4 loader
Browse files Browse the repository at this point in the history
  • Loading branch information
simonrepp committed Mar 21, 2019
1 parent 0097649 commit 4dfe6f6
Show file tree
Hide file tree
Showing 23 changed files with 587 additions and 1 deletion.
142 changes: 142 additions & 0 deletions blueprints/loaders/ipv4.eno
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: ipv4

-- description
Accepts only IPv4 addresses, returns the validated adress as a string.
-- description

# messages

ipv4_required:
de = Eine valide IPv4 Adresse ist erforderlich, zum Beispiel '192.168.0.1'.
en = A valid IPv4 address is required, for instance '192.168.0.1'.
es = Se requiere una valida dirección IPv4, por ejemplo '192.168.0.1'.

# implementations

## javascript

prelude:
- const IPV4_REGEX = /^\s*((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}))\s*$/;

-- code
value => {
const match = IPV4_REGEX.exec(value);

if(match) {
const octet1 = parseInt(match[2]);
const octet2 = parseInt(match[3]);
const octet3 = parseInt(match[4]);
const octet4 = parseInt(match[5]);

if(octet1 >= 0 && octet1 <= 255 &&
octet2 >= 0 && octet2 <= 255 &&
octet3 >= 0 && octet3 <= 255 &&
octet4 >= 0 && octet4 <= 255)
return match[1];
}

throw 'ipv4_required';
}
-- code

specs:
'0.0.0.0' = '0.0.0.0'
'255.255.255.255' = '255.255.255.255'
'192.168.0.1' = '192.168.0.1'
'10.10.10.10' = '10.10.10.10'
'255.255.255.256' =
'localhost' =
'4.staging.production.lan' =

## php

prelude:
- use \Exception;
- private const IPV4_REGEXP = '/^\s*((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}))\s*$/';

-- code
public static function ipv4($value) {
$matched = preg_match(self::IPV4_REGEXP, $value, $match);

if($matched) {
$octet1 = intval($match[2]);
$octet2 = intval($match[3]);
$octet3 = intval($match[4]);
$octet4 = intval($match[5]);

if($octet1 >= 0 && $octet1 <= 255 &&
$octet2 >= 0 && $octet2 <= 255 &&
$octet3 >= 0 && $octet3 <= 255 &&
$octet4 >= 0 && $octet4 <= 255)
return $match[1];
}

throw new Exception('ipv4_required');
}
-- code

specs:
'0.0.0.0' = '0.0.0.0'
'255.255.255.255' = '255.255.255.255'
'192.168.0.1' = '192.168.0.1'
'10.10.10.10' = '10.10.10.10'
'255.255.255.256' =
'localhost' =
'4.staging.production.lan' =

## python

prelude:
- import re
- IPV4_RE = re.compile(r'^\s*((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}))\s*$')

-- code
def ipv4(value):
match = IPV4_RE.match(value)

if (match and
0 <= int(match.group(2)) <= 255 and
0 <= int(match.group(3)) <= 255 and
0 <= int(match.group(4)) <= 255 and
0 <= int(match.group(5)) <= 255):
return match.group(1)

raise ValueError('ipv4_required')
-- code

specs:
'0.0.0.0' = '0.0.0.0'
'255.255.255.255' = '255.255.255.255'
'192.168.0.1' = '192.168.0.1'
'10.10.10.10' = '10.10.10.10'
'255.255.255.256' =
'localhost' =
'4.staging.production.lan' =

## ruby

prelude:
- IPV4_REGEXP = /^\s*((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}))\s*$/

-- code
def self.ipv4(value)
match = value.match(IPV4_REGEXP)

return match[1] if match &&
match[2].to_i.between?(0, 255) &&
match[3].to_i.between?(0, 255) &&
match[4].to_i.between?(0, 255) &&
match[5].to_i.between?(0, 255)

raise 'ipv4_required'
end
-- code

specs:
'0.0.0.0' = '0.0.0.0'
'255.255.255.255' = '255.255.255.255'
'192.168.0.1' = '192.168.0.1'
'10.10.10.10' = '10.10.10.10'
'255.255.255.256' =
'localhost' =
'4.staging.production.lan' =
15 changes: 15 additions & 0 deletions javascript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,21 @@ integer('42'); // returns 42
`'42,0'` throws an error.
`'4 2'` throws an error.
`'fortytwo'` throws an error.
### ipv4

```js
const { ipv4 } = require('enotype');

ipv4('0.0.0.0'); // returns '0.0.0.0'
```

`'0.0.0.0'` returns `'0.0.0.0'`.
`'255.255.255.255'` returns `'255.255.255.255'`.
`'192.168.0.1'` returns `'192.168.0.1'`.
`'10.10.10.10'` returns `'10.10.10.10'`.
`'255.255.255.256'` throws an error.
`'localhost'` throws an error.
`'4.staging.production.lan'` throws an error.
### json

```js
Expand Down
20 changes: 20 additions & 0 deletions javascript/lib/de.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const DATETIME_REGEX = /^\s*(\d{4})(?:-(\d\d)(?:-(\d\d)(?:T(\d\d):(\d\d)(?::(\d\
const EMAIL_REGEX = /^\s*[^@\s]+@[^@\s]+\.[^@\s]+\s*$/;
const FLOAT_REGEX = /^\s*-?\d+(\.\d+)?\s*$/;
const INTEGER_REGEX = /^\s*-?\d+\s*$/;
const IPV4_REGEX = /^\s*((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}))\s*$/;
const LAT_LNG_REGEX = /^\s*(-?\d{1,3}(?:\.\d+)?)\s*,\s*(-?\d{1,3}(?:\.\d+)?)\s*$/;
const SLUG_REGEX = /^[0-9a-z\-_]+$/;
const URL_REGEX = /^\s*https?:\/\/[^\s.]+\.\S+\s*$/;
Expand Down Expand Up @@ -71,6 +72,25 @@ exports.integer = value => {
return parseInt(value);
};

exports.ipv4 = value => {
const match = IPV4_REGEX.exec(value);

if(match) {
const octet1 = parseInt(match[2]);
const octet2 = parseInt(match[3]);
const octet3 = parseInt(match[4]);
const octet4 = parseInt(match[5]);

if(octet1 >= 0 && octet1 <= 255 &&
octet2 >= 0 && octet2 <= 255 &&
octet3 >= 0 && octet3 <= 255 &&
octet4 >= 0 && octet4 <= 255)
return match[1];
}

throw 'Eine valide IPv4 Adresse ist erforderlich, zum Beispiel \'192.168.0.1\'.';
};

exports.json = value => {
try {
return JSON.parse(value);
Expand Down
20 changes: 20 additions & 0 deletions javascript/lib/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const DATETIME_REGEX = /^\s*(\d{4})(?:-(\d\d)(?:-(\d\d)(?:T(\d\d):(\d\d)(?::(\d\
const EMAIL_REGEX = /^\s*[^@\s]+@[^@\s]+\.[^@\s]+\s*$/;
const FLOAT_REGEX = /^\s*-?\d+(\.\d+)?\s*$/;
const INTEGER_REGEX = /^\s*-?\d+\s*$/;
const IPV4_REGEX = /^\s*((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}))\s*$/;
const LAT_LNG_REGEX = /^\s*(-?\d{1,3}(?:\.\d+)?)\s*,\s*(-?\d{1,3}(?:\.\d+)?)\s*$/;
const SLUG_REGEX = /^[0-9a-z\-_]+$/;
const URL_REGEX = /^\s*https?:\/\/[^\s.]+\.\S+\s*$/;
Expand Down Expand Up @@ -71,6 +72,25 @@ exports.integer = value => {
return parseInt(value);
};

exports.ipv4 = value => {
const match = IPV4_REGEX.exec(value);

if(match) {
const octet1 = parseInt(match[2]);
const octet2 = parseInt(match[3]);
const octet3 = parseInt(match[4]);
const octet4 = parseInt(match[5]);

if(octet1 >= 0 && octet1 <= 255 &&
octet2 >= 0 && octet2 <= 255 &&
octet3 >= 0 && octet3 <= 255 &&
octet4 >= 0 && octet4 <= 255)
return match[1];
}

throw 'A valid IPv4 address is required, for instance \'192.168.0.1\'.';
};

exports.json = value => {
try {
return JSON.parse(value);
Expand Down
20 changes: 20 additions & 0 deletions javascript/lib/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const DATETIME_REGEX = /^\s*(\d{4})(?:-(\d\d)(?:-(\d\d)(?:T(\d\d):(\d\d)(?::(\d\
const EMAIL_REGEX = /^\s*[^@\s]+@[^@\s]+\.[^@\s]+\s*$/;
const FLOAT_REGEX = /^\s*-?\d+(\.\d+)?\s*$/;
const INTEGER_REGEX = /^\s*-?\d+\s*$/;
const IPV4_REGEX = /^\s*((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}))\s*$/;
const LAT_LNG_REGEX = /^\s*(-?\d{1,3}(?:\.\d+)?)\s*,\s*(-?\d{1,3}(?:\.\d+)?)\s*$/;
const SLUG_REGEX = /^[0-9a-z\-_]+$/;
const URL_REGEX = /^\s*https?:\/\/[^\s.]+\.\S+\s*$/;
Expand Down Expand Up @@ -71,6 +72,25 @@ exports.integer = value => {
return parseInt(value);
};

exports.ipv4 = value => {
const match = IPV4_REGEX.exec(value);

if(match) {
const octet1 = parseInt(match[2]);
const octet2 = parseInt(match[3]);
const octet3 = parseInt(match[4]);
const octet4 = parseInt(match[5]);

if(octet1 >= 0 && octet1 <= 255 &&
octet2 >= 0 && octet2 <= 255 &&
octet3 >= 0 && octet3 <= 255 &&
octet4 >= 0 && octet4 <= 255)
return match[1];
}

throw 'Se requiere una valida dirección IPv4, por ejemplo \'192.168.0.1\'.';
};

exports.json = value => {
try {
return JSON.parse(value);
Expand Down
45 changes: 45 additions & 0 deletions javascript/specs/ipv4.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const { ipv4 } = require('..');

describe('ipv4', () => {
describe('with \'0.0.0.0\'', () => {
it('produces the expected result', () => {
expect(ipv4('0.0.0.0')).toBe('0.0.0.0');
});
});

describe('with \'255.255.255.255\'', () => {
it('produces the expected result', () => {
expect(ipv4('255.255.255.255')).toBe('255.255.255.255');
});
});

describe('with \'192.168.0.1\'', () => {
it('produces the expected result', () => {
expect(ipv4('192.168.0.1')).toBe('192.168.0.1');
});
});

describe('with \'10.10.10.10\'', () => {
it('produces the expected result', () => {
expect(ipv4('10.10.10.10')).toBe('10.10.10.10');
});
});

describe('with \'255.255.255.256\'', () => {
it('throws an error', () => {
expect(() => ipv4('255.255.255.256')).toThrow();
});
});

describe('with \'localhost\'', () => {
it('throws an error', () => {
expect(() => ipv4('localhost')).toThrow();
});
});

describe('with \'4.staging.production.lan\'', () => {
it('throws an error', () => {
expect(() => ipv4('4.staging.production.lan')).toThrow();
});
});
});
17 changes: 17 additions & 0 deletions php/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,23 @@ Loaders::integer('42'); // returns 42
`'42,0'` throws an error.
`'4 2'` throws an error.
`'fortytwo'` throws an error.
### ipv4

```php
<?php

use Enotype\Loaders;

Loaders::ipv4('0.0.0.0'); // returns '0.0.0.0'
```

`'0.0.0.0'` returns `'0.0.0.0'`.
`'255.255.255.255'` returns `'255.255.255.255'`.
`'192.168.0.1'` returns `'192.168.0.1'`.
`'10.10.10.10'` returns `'10.10.10.10'`.
`'255.255.255.256'` throws an error.
`'localhost'` throws an error.
`'4.staging.production.lan'` throws an error.
### json

```php
Expand Down
47 changes: 47 additions & 0 deletions php/spec/ipv4.spec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php declare(strict_types=1);

use Enotype\Loaders;

describe('ipv4', function() {
describe('with \'0.0.0.0\'', function() {
it('produces the expected result', function() {
expect(Loaders::ipv4('0.0.0.0'))->toEqual('0.0.0.0');
});
});

describe('with \'255.255.255.255\'', function() {
it('produces the expected result', function() {
expect(Loaders::ipv4('255.255.255.255'))->toEqual('255.255.255.255');
});
});

describe('with \'192.168.0.1\'', function() {
it('produces the expected result', function() {
expect(Loaders::ipv4('192.168.0.1'))->toEqual('192.168.0.1');
});
});

describe('with \'10.10.10.10\'', function() {
it('produces the expected result', function() {
expect(Loaders::ipv4('10.10.10.10'))->toEqual('10.10.10.10');
});
});

describe('with \'255.255.255.256\'', function() {
it('throws an exception', function() {
expect(function() { Loaders::ipv4('255.255.255.256'); })->toThrow();
});
});

describe('with \'localhost\'', function() {
it('throws an exception', function() {
expect(function() { Loaders::ipv4('localhost'); })->toThrow();
});
});

describe('with \'4.staging.production.lan\'', function() {
it('throws an exception', function() {
expect(function() { Loaders::ipv4('4.staging.production.lan'); })->toThrow();
});
});
});
Loading

0 comments on commit 4dfe6f6

Please sign in to comment.