```ts
/**
 * Converts a prefix length to a network mask in dotted-quad format.
 * @param prefix - The number of leading one bits in the mask (0-32).
 * @returns A string representing the network mask.
 */
export function maskFromPrefix(prefix: number): string {
    if (!Number.isInteger(prefix) || prefix < 0 || prefix > 32) {
        throw new Error('Invalid prefix');
    }
    const segments = Array(4).fill(0);
    for (let i = 0; i < prefix; ++i) {
        segments[Math.floor(i / 8)] |= 1 << (7 - i % 8);
    }
    return segments.map(segment => segment.toString()).join('.');
}

/**
 * Converts a network mask in dotted-quad format to its prefix length.
 * @param mask - The network mask as a string.
 * @returns The number of leading one bits in the mask.
 */
export function prefixFromMask(mask: string): number {
    if (typeof mask !== 'string') {
        throw new Error('Invalid input');
    }
    const parts = mask.split('.');
    if (parts.length !== 4) {
        throw new Error('Invalid mask format');
    }
    let prefix = 0;
    for (const part of parts) {
        if (!/^\d+$/.test(part)) {
            throw new Error('Invalid numeric field in mask');
        }
        const num = parseInt(part, 10);
        if (num > 255 || (part.length > 1 && part.startsWith('0'))) {
            throw new Error('Invalid octet in mask');
        }
        prefix += (32 - Math.floor(Math.log2(num + 1))) & 7;
    }
    return prefix;
}
```