repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
nushell/modules/proquint.nu
Rawconst CONSONANTS = "bdfghjklmnprstvz" | split chars
const VOWELS = "aiou" | split chars
def consonant-value [letter: string] {
$CONSONANTS | enumerate | where item == $letter | first | get index
}
def vowel-value [letter: string] {
$VOWELS | enumerate | where item == $letter | first | get index
}
# Encode binary as lowercase proquint blocks.
# Each five-letter CVCVC block holds two bytes; a final three-letter CVC block
# holds one byte. Its last consonant is restricted to b, d, f, or g.
export def main [value?: binary] {
let bytes = if $value == null { $in } else { $value }
if ($bytes | describe) != "binary" {
error make {msg: "proquint requires binary input"}
}
$bytes
| chunks 2
| each {|chunk|
let high = $chunk.0
let low = $chunk.1?
if $low == null {
[
($CONSONANTS | get ($high // 16))
($VOWELS | get (($high // 4) mod 4))
($CONSONANTS | get ($high mod 4))
] | str join
} else {
let word = $high * 256 + $low
[
($CONSONANTS | get ($word // 4096))
($VOWELS | get (($word // 1024) mod 4))
($CONSONANTS | get (($word // 64) mod 16))
($VOWELS | get (($word // 16) mod 4))
($CONSONANTS | get ($word mod 16))
] | str join
}
}
| str join "-"
}
# Decode proquints to binary, without inferring a Nushell value type.
export def decode [value?: string] {
let text = if $value == null { $in } else { $value }
if ($text | describe) != "string" {
error make {msg: "proquint decode requires text input"}
}
if $text == "" { return 0x[] }
let blocks = $text | split row "-"
let last = ($blocks | length) - 1
$blocks
| enumerate
| each {|entry|
let block = $entry.item
let letters = $block | split chars
if $block =~ '^[bdfghjklmnprstvz][aiou][bdfghjklmnprstvz][aiou][bdfghjklmnprstvz]$' {
let word = (
(consonant-value ($letters | get 0)) * 4096
+ (vowel-value ($letters | get 1)) * 1024
+ (consonant-value ($letters | get 2)) * 64
+ (vowel-value ($letters | get 3)) * 16
+ (consonant-value ($letters | get 4))
)
[
(($word // 256) | into binary --compact --endian big)
(($word mod 256) | into binary --compact --endian big)
] | bytes collect
} else if $entry.index == $last and $block =~ '^[bdfghjklmnprstvz][aiou][bdfg]$' {
let byte = (
(consonant-value ($letters | get 0)) * 16
+ (vowel-value ($letters | get 1)) * 4
+ (consonant-value ($letters | get 2))
)
$byte | into binary --compact --endian big
} else {
error make {msg: $"invalid proquint block: ($block)"}
}
}
| bytes collect
}