mirror of
https://github.com/BorysLevytskyi/BitwiseCmd.git
synced 2026-01-16 17:02:38 +01:00
140 lines
4.6 KiB
TypeScript
140 lines
4.6 KiB
TypeScript
import { IpAddress, IpAddressWithSubnetMask, SubnetCommand, VpcCommand } from './models';
|
|
|
|
export type ParsedIpObject = IpAddress | IpAddressWithSubnetMask;
|
|
|
|
export type ParsingResult = ParsedIpObject[] |
|
|
SubnetCommand |
|
|
ParsingError |
|
|
VpcCommand |
|
|
null;
|
|
|
|
const CMD_SUBNET = 'subnet';
|
|
const CMD_VPC = 'vpc';
|
|
|
|
const ipAddressParser = {
|
|
parse: function(input: string) : ParsingResult {
|
|
|
|
const result = this.parseCommand(input);
|
|
|
|
const matches = this.getMaches(result.nextInput);
|
|
const correctInputs = matches.filter(m => m.matches != null);
|
|
const incorrectInputs = matches.filter(m => m.matches == null);
|
|
|
|
if(correctInputs.length == 0)
|
|
return null;
|
|
|
|
if(incorrectInputs.length > 0) {
|
|
return new ParsingError(`Value(s) ${incorrectInputs.map(v => v.input).join(',')} was not recognized as valid ip address or ip address with a subnet mask`);
|
|
}
|
|
|
|
const parsedObjects = matches.map(m => this.parseSingle(m.matches!, m.input));
|
|
const parsingErrors = parsedObjects.filter(p => p instanceof ParsingError);
|
|
|
|
if(parsingErrors.length > 0) {
|
|
return parsingErrors[0] as ParsingError;
|
|
}
|
|
|
|
if(result.command != null) {
|
|
const cmd =
|
|
result.command == CMD_SUBNET
|
|
? this.createSubnetDefinition(parsedObjects as ParsedIpObject[])
|
|
: this.createVpcDefinition(parsedObjects as ParsedIpObject[]);
|
|
|
|
return cmd;
|
|
}
|
|
|
|
return parsedObjects as ParsedIpObject[];
|
|
},
|
|
|
|
parseCommand(input : string) : { command: null | string, nextInput: string } {
|
|
|
|
|
|
|
|
if(input.startsWith(CMD_SUBNET))
|
|
return { command: CMD_SUBNET, nextInput: input.substring(CMD_SUBNET.length)};
|
|
|
|
if(input.startsWith(CMD_VPC)) {
|
|
return {command: CMD_VPC, nextInput: input.substring(CMD_VPC.length)};
|
|
}
|
|
|
|
return { command: null, nextInput: input };
|
|
},
|
|
|
|
getMaches(input : string) : { matches: RegExpExecArray | null, input: string }[] {
|
|
|
|
return input.
|
|
replace(/[\t\s]+/g, ' ')
|
|
.split(' ')
|
|
.filter(s => s.length>0)
|
|
.map(s => {
|
|
const ipV4Regex = /^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})(\/\d+)?$/;
|
|
const matches = ipV4Regex.exec(s);
|
|
|
|
if(matches == null || matches.length === 0)
|
|
return {matches: null, input: s};
|
|
|
|
return {matches, input: s};
|
|
});
|
|
},
|
|
|
|
parseSingle(matches : RegExpExecArray, input: string) : ParsedIpObject | ParsingError {
|
|
const invalid = (n: number) => n < 0 || n > 255;
|
|
|
|
const first = parseInt(matches[1]);
|
|
const second = parseInt(matches[2]);
|
|
const third = parseInt(matches[3]);
|
|
const fourth = parseInt(matches[4]);
|
|
|
|
if(invalid(first) || invalid(second) || invalid(third) || invalid(fourth))
|
|
return new ParsingError(`${input} doesn't represent a valid IP address space`);
|
|
|
|
const ipAddress = new IpAddress(first, second, third, fourth);
|
|
|
|
if(matches[5]) {
|
|
const maskPart = matches[5].substr(1);
|
|
const maskBits = parseInt(maskPart);
|
|
|
|
if(maskBits > 32) {
|
|
return new ParsingError(`Subnet mask value in ${input} is out of range`);
|
|
}
|
|
|
|
return new IpAddressWithSubnetMask(ipAddress, maskBits);
|
|
}
|
|
|
|
return ipAddress;
|
|
},
|
|
|
|
createSubnetDefinition(items: ParsedIpObject[]) : SubnetCommand | ParsingError {
|
|
if(items.length != 1)
|
|
return new ParsingError("Incorrect network definition");
|
|
|
|
const first = items[0];
|
|
if(first instanceof IpAddressWithSubnetMask) {
|
|
return new SubnetCommand(first);
|
|
}
|
|
|
|
return new ParsingError("Network definition requires subnet mask");
|
|
},
|
|
|
|
createVpcDefinition(items: ParsedIpObject[]) : VpcCommand | ParsingError {
|
|
|
|
if(items.length != 1)
|
|
return new ParsingError("Incorrect VPC definition");
|
|
|
|
const first = items[0];
|
|
if(first instanceof IpAddressWithSubnetMask) {
|
|
return new VpcCommand(first);
|
|
}
|
|
|
|
return new ParsingError("VPC definition requires subnet mask");
|
|
}
|
|
}
|
|
|
|
export class ParsingError {
|
|
errorMessage: string;
|
|
constructor(message: string) {
|
|
this.errorMessage = message;
|
|
}
|
|
}
|
|
|
|
export default ipAddressParser; |