Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,204 @@
|
||||
module yaml
|
||||
|
||||
import strings
|
||||
|
||||
// write_spaces appends `n` spaces to `sb`.
|
||||
fn write_spaces(mut sb strings.Builder, n int) {
|
||||
for _ in 0 .. n {
|
||||
sb.write_u8(` `)
|
||||
}
|
||||
}
|
||||
|
||||
// emit_yaml_any streams `value` into `sb` as block-style YAML.
|
||||
fn emit_yaml_any(mut sb strings.Builder, value Any, indent int) {
|
||||
match value {
|
||||
map[string]Any { emit_yaml_map(mut sb, value, indent) }
|
||||
[]Any { emit_yaml_array(mut sb, value, indent) }
|
||||
else { emit_yaml_scalar(mut sb, value) }
|
||||
}
|
||||
}
|
||||
|
||||
// emit_yaml_map writes `value` as a block-style YAML mapping. An empty map
|
||||
// is emitted as the inline `{}` form; otherwise each key is JSON-quoted (see
|
||||
// `write_json_escaped_string`) and nested containers indent one level deeper.
|
||||
fn emit_yaml_map(mut sb strings.Builder, value map[string]Any, indent int) {
|
||||
if value.len == 0 {
|
||||
sb.write_string('{}')
|
||||
return
|
||||
}
|
||||
mut first := true
|
||||
for key, item in value {
|
||||
if !first {
|
||||
sb.write_u8(`\n`)
|
||||
}
|
||||
first = false
|
||||
write_spaces(mut sb, indent)
|
||||
write_json_escaped_string(mut sb, key)
|
||||
match item {
|
||||
map[string]Any, []Any {
|
||||
sb.write_u8(`:`)
|
||||
sb.write_u8(`\n`)
|
||||
emit_yaml_any(mut sb, item, indent + 2)
|
||||
}
|
||||
else {
|
||||
sb.write_string(': ')
|
||||
emit_yaml_scalar(mut sb, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// emit_yaml_array writes `value` as a block-style YAML sequence. An empty
|
||||
// array is emitted as the inline `[]` form; otherwise each item is prefixed
|
||||
// with `- ` and nested containers indent one level deeper.
|
||||
fn emit_yaml_array(mut sb strings.Builder, value []Any, indent int) {
|
||||
if value.len == 0 {
|
||||
sb.write_string('[]')
|
||||
return
|
||||
}
|
||||
mut first := true
|
||||
for item in value {
|
||||
if !first {
|
||||
sb.write_u8(`\n`)
|
||||
}
|
||||
first = false
|
||||
write_spaces(mut sb, indent)
|
||||
match item {
|
||||
map[string]Any, []Any {
|
||||
sb.write_u8(`-`)
|
||||
sb.write_u8(`\n`)
|
||||
emit_yaml_any(mut sb, item, indent + 2)
|
||||
}
|
||||
else {
|
||||
sb.write_string('- ')
|
||||
emit_yaml_scalar(mut sb, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// emit_yaml_scalar writes `value` as a single YAML scalar token: strings go
|
||||
// through `write_json_escaped_string`, booleans / numbers / null print their
|
||||
// literal form. The container branch is type-required by V's exhaustive
|
||||
// `match` over `Any` but is unreachable: `emit_yaml_any` routes maps and
|
||||
// arrays to their dedicated emitters before falling back here.
|
||||
fn emit_yaml_scalar(mut sb strings.Builder, value Any) {
|
||||
match value {
|
||||
string { write_json_escaped_string(mut sb, value) }
|
||||
bool { sb.write_string(if value { 'true' } else { 'false' }) }
|
||||
f64 { sb.write_string(value.str()) }
|
||||
i64 { sb.write_string(value.str()) }
|
||||
int { sb.write_string(value.str()) }
|
||||
u64 { sb.write_string(value.str()) }
|
||||
Null { sb.write_string('null') }
|
||||
[]Any, map[string]Any { emit_yaml_any(mut sb, value, 0) }
|
||||
}
|
||||
}
|
||||
|
||||
// write_json_escaped_string writes `value` as a JSON string literal directly
|
||||
// into `sb`. Matches `json2.encode`'s rules: standard short escapes for control
|
||||
// chars, `\u00XX` for the rest below 0x20, and UTF-8 bytes passed through
|
||||
// verbatim (no per-byte `\uXXXX` re-escape). Passes safe runs through in bulk
|
||||
// via `write_string` on the original slice — the overwhelmingly common case for
|
||||
// human YAML — and only switches to per-byte handling at escape boundaries.
|
||||
fn write_json_escaped_string(mut sb strings.Builder, value string) {
|
||||
sb.write_u8(`"`)
|
||||
mut start := 0
|
||||
for i := 0; i < value.len; i++ {
|
||||
c := value[i]
|
||||
if c >= 0x20 && c != `"` && c != `\\` {
|
||||
continue
|
||||
}
|
||||
if start < i {
|
||||
sb.write_string(value[start..i])
|
||||
}
|
||||
match c {
|
||||
`"` {
|
||||
sb.write_string('\\"')
|
||||
}
|
||||
`\\` {
|
||||
sb.write_string('\\\\')
|
||||
}
|
||||
`\n` {
|
||||
sb.write_string('\\n')
|
||||
}
|
||||
`\r` {
|
||||
sb.write_string('\\r')
|
||||
}
|
||||
`\t` {
|
||||
sb.write_string('\\t')
|
||||
}
|
||||
`\b` {
|
||||
sb.write_string('\\b')
|
||||
}
|
||||
`\f` {
|
||||
sb.write_string('\\f')
|
||||
}
|
||||
else {
|
||||
sb.write_string('\\u00')
|
||||
hex := '0123456789abcdef'
|
||||
sb.write_u8(hex[(c >> 4) & 0xf])
|
||||
sb.write_u8(hex[c & 0xf])
|
||||
}
|
||||
}
|
||||
|
||||
start = i + 1
|
||||
}
|
||||
if start < value.len {
|
||||
sb.write_string(value[start..])
|
||||
}
|
||||
sb.write_u8(`"`)
|
||||
}
|
||||
|
||||
// emit_any_as_json writes `a` as a compact JSON document.
|
||||
fn emit_any_as_json(mut sb strings.Builder, a Any) {
|
||||
match a {
|
||||
map[string]Any {
|
||||
sb.write_u8(`{`)
|
||||
mut first := true
|
||||
for key, value in a {
|
||||
if !first {
|
||||
sb.write_u8(`,`)
|
||||
}
|
||||
first = false
|
||||
write_json_escaped_string(mut sb, key)
|
||||
sb.write_u8(`:`)
|
||||
emit_any_as_json(mut sb, value)
|
||||
}
|
||||
sb.write_u8(`}`)
|
||||
}
|
||||
[]Any {
|
||||
sb.write_u8(`[`)
|
||||
mut first := true
|
||||
for value in a {
|
||||
if !first {
|
||||
sb.write_u8(`,`)
|
||||
}
|
||||
first = false
|
||||
emit_any_as_json(mut sb, value)
|
||||
}
|
||||
sb.write_u8(`]`)
|
||||
}
|
||||
string {
|
||||
write_json_escaped_string(mut sb, a)
|
||||
}
|
||||
bool {
|
||||
sb.write_string(if a { 'true' } else { 'false' })
|
||||
}
|
||||
f64 {
|
||||
sb.write_string(a.str())
|
||||
}
|
||||
i64 {
|
||||
sb.write_string(a.str())
|
||||
}
|
||||
int {
|
||||
sb.write_string(a.str())
|
||||
}
|
||||
u64 {
|
||||
sb.write_string(a.str())
|
||||
}
|
||||
Null {
|
||||
sb.write_string('null')
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user