///|
/// moonfig 示例:整数与字符串不会互相顶替。
///
/// 运行:`moon run examples/strict_types`
///
/// 两条来源内容完全一样,只有 `port` 的写法不同——一个是数字 `5432`,
/// 一个是字符串 `"5432"`。下面逐个展示它在两层 API 上的结果:
///
/// - 按键取值:直接看 `Value` 的形状,形状不符就报错,不做转换
/// - 提取到结构体:整数映射为 JSON 数字、字符串映射为 JSON 字符串,
/// 两条路互不交叉
///|
using @config {type Config, type StringSource}
///|
using @jsonfmt {type JsonFormat, extract_from}
///|
/// 端口声明成数字,只该接受数字来源
struct NumericPort {
port : Int32
name : String
} derive(@json.FromJson)
///|
pub extend NumericPort with @json.FromJson::{from_json}
///|
/// 端口声明成字符串,只该接受字符串来源
struct TextualPort {
port : String
name : String
} derive(@json.FromJson)
///|
pub extend TextualPort with @json.FromJson::{from_json}
///|
/// 取整数;失败时把错误原文带回来,方便直接看提示
fn read_int(cfg : Config, path : String) -> String {
cfg.get_int(path).to_string() catch {
e => "error: \{e}"
}
}
///|
/// 取字符串;失败时把错误原文带回来
fn read_str(cfg : Config, path : String) -> String {
cfg.get_string(path) catch {
e => "error: \{e}"
}
}
///|
/// 数字端口结构体
fn read_numeric(cfg : Config) -> String {
try {
let v : NumericPort = extract_from(cfg, "db")
"port = \{v.port}, name = \{v.name}"
} catch {
e => "error: \{e}"
}
}
///|
/// 字符串端口结构体
fn read_textual(cfg : Config) -> String {
try {
let v : TextualPort = extract_from(cfg, "db")
"port = \"\{v.port}\", name = \{v.name}"
} catch {
e => "error: \{e}"
}
}
///|
fn main raise {
let numeric = Config::new()
.add(
StringSource::new(
"{\"db\":{\"port\":5432,\"name\":\"main\"}}",
JsonFormat::new(),
),
)
.build()
let textual = Config::new()
.add(
StringSource::new(
"{\"db\":{\"port\":\"5432\",\"name\":\"main\"}}",
JsonFormat::new(),
),
)
.build()
let n_int = read_int(numeric, "db.port")
let t_int = read_int(textual, "db.port")
let n_str = read_str(numeric, "db.port")
let t_str = read_str(textual, "db.port")
println("== Read by key ==")
println("numeric source get_int -> \{n_int}") // 5432
println("string source get_int -> \{t_int}") // error: expected Int, got Str
println("numeric source get_string -> \{n_str}") // error: expected Str, got Int
println("string source get_string -> \{t_str}") // "5432"
let n_num = read_numeric(numeric)
let t_num = read_numeric(textual)
let n_txt = read_textual(numeric)
let t_txt = read_textual(textual)
println("")
println("== Extract into struct ==")
println("numeric source -> NumericPort \{n_num}") // port = 5432, name = main
println("numeric source -> TextualPort \{n_txt}") // error: key 'db.port': expected Str, got Int
println("string source -> NumericPort \{t_num}") // error: key 'db.port': expected Int, got Str
println("string source -> TextualPort \{t_txt}") // port = "5432", name = main
}