typia
Version:
Superfast runtime validators with only one line
54 lines (48 loc) • 2.01 kB
text/typescript
import { _randomInteger } from "./_randomInteger";
import { _randomString } from "./_randomString";
import { _ILengthProps } from "./_randomStringLength";
export const _randomFormatHostname = (props?: _ILengthProps): string => {
if (props?.minLength === undefined && props?.maxLength === undefined)
return `${random(10)}.${random(3)}`;
// A hostname is dot-joined labels of 1..63 chars whose total is capped at 253,
// so the requested length is realized by splitting it across enough labels.
return _randomHostnameLabels(pickLength(props));
};
const MAX_TOTAL = 253;
const MAX_LABEL = 63;
const pickLength = (props: _ILengthProps): number => {
let low: number = props.minLength === undefined ? 1 : props.minLength;
if (low < 1) low = 1;
const high: number =
props.maxLength === undefined
? Math.min(MAX_TOTAL, low + 14)
: Math.min(MAX_TOTAL, props.maxLength);
if (high < low)
throw new Error(
"unable to generate a random hostname satisfying both the format and the length constraints.",
);
return _randomInteger({ type: "integer", minimum: low, maximum: high });
};
/**
* Builds dot-joined hostname labels totaling exactly `length` characters, each
* label within 63 chars. Shared with the idn-hostname generator, which reserves
* a fixed `.<tld>` suffix and realizes the rest as these leading labels.
*/
export const _randomHostnameLabels = (length: number): string => {
const parts: string[] = [];
let remaining: number = length;
while (remaining > MAX_LABEL + 1) {
// one full label plus its joining dot
parts.push(random(MAX_LABEL));
remaining -= MAX_LABEL + 1;
}
if (remaining <= MAX_LABEL) parts.push(random(remaining));
else {
// remaining === MAX_LABEL + 1: two labels keep every label within 63 chars
parts.push(random(MAX_LABEL - 1));
parts.push(random(1));
}
return parts.join(".");
};
const random = (length: number) =>
_randomString({ type: "string", minLength: length, maxLength: length });