mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 15:44:21 +01:00
190 lines
5.1 KiB
Rust
190 lines
5.1 KiB
Rust
use serde::ser::{SerializeStruct, Serializer};
|
|
use serde::Serialize;
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub enum Value {
|
|
String(String),
|
|
Integer(i64),
|
|
Boolean(bool),
|
|
OptString,
|
|
OptInteger,
|
|
OptBoolean,
|
|
}
|
|
|
|
impl Value {
|
|
/// Returns true if the `Value` is a String. Returns false otherwise.
|
|
///
|
|
/// For any Value on which `is_string` returns true, `as_str` is guaranteed
|
|
/// to return the string slice.
|
|
pub fn is_string(&self) -> bool {
|
|
self.as_str().is_some()
|
|
}
|
|
|
|
/// If the `Value` is a String, returns the associated str. Returns None
|
|
/// otherwise.
|
|
pub fn as_str(&self) -> Option<&str> {
|
|
match self {
|
|
Value::String(s) => Some(s),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
/// Returns true if the `Value` is an integer between `i64::MIN` and
|
|
/// `i64::MAX`.
|
|
///
|
|
/// For any Value on which `is_i64` returns true, `as_i64` is guaranteed to
|
|
/// return the integer value.
|
|
pub fn is_i64(&self) -> bool {
|
|
self.as_i64().is_some()
|
|
|
|
|
|
}
|
|
|
|
/// If the `Value` is an integer, represent it as i64. Returns
|
|
/// None otherwise.
|
|
pub fn as_i64(&self) -> Option<i64> {
|
|
match *self {
|
|
Value::Integer(n) => Some(n),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
/// Returns true if the `Value` is a Boolean. Returns false otherwise.
|
|
///
|
|
/// For any Value on which `is_boolean` returns true, `as_bool` is
|
|
/// guaranteed to return the boolean value.
|
|
pub fn is_boolean(&self) -> bool {
|
|
self.as_bool().is_some()
|
|
}
|
|
|
|
/// If the `Value` is a Boolean, returns the associated bool. Returns None
|
|
/// otherwise.
|
|
pub fn as_bool(&self) -> Option<bool> {
|
|
match *self {
|
|
Value::Boolean(b) => Some(b),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// An stringly typed option that is passed to
|
|
#[derive(Clone, Debug)]
|
|
pub struct ConfigOption {
|
|
name: String,
|
|
pub(crate) value: Option<Value>,
|
|
default: Value,
|
|
description: String,
|
|
}
|
|
|
|
impl ConfigOption {
|
|
pub fn name(&self) -> &str {
|
|
&self.name
|
|
}
|
|
pub fn default(&self) -> &Value {
|
|
&self.default
|
|
}
|
|
}
|
|
|
|
// When we serialize we don't add the value. This is because we only
|
|
// ever serialize when we pass the option back to lightningd during
|
|
// the getmanifest call.
|
|
impl Serialize for ConfigOption {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
let mut s = serializer.serialize_struct("ConfigOption", 4)?;
|
|
s.serialize_field("name", &self.name)?;
|
|
match &self.default {
|
|
Value::String(ss) => {
|
|
s.serialize_field("type", "string")?;
|
|
s.serialize_field("default", ss)?;
|
|
}
|
|
Value::Integer(i) => {
|
|
s.serialize_field("type", "int")?;
|
|
s.serialize_field("default", i)?;
|
|
}
|
|
Value::Boolean(b) => {
|
|
s.serialize_field("type", "bool")?;
|
|
s.serialize_field("default", b)?;
|
|
}
|
|
Value::OptString => {
|
|
s.serialize_field("type", "string")?;
|
|
}
|
|
Value::OptInteger => {
|
|
s.serialize_field("type", "int")?;
|
|
}
|
|
Value::OptBoolean => {
|
|
s.serialize_field("type", "bool")?;
|
|
}
|
|
}
|
|
|
|
s.serialize_field("description", &self.description)?;
|
|
s.end()
|
|
}
|
|
}
|
|
impl ConfigOption {
|
|
pub fn new(name: &str, default: Value, description: &str) -> Self {
|
|
Self {
|
|
name: name.to_string(),
|
|
default,
|
|
description: description.to_string(),
|
|
value: None,
|
|
}
|
|
}
|
|
|
|
pub fn value(&self) -> Value {
|
|
match &self.value {
|
|
None => self.default.clone(),
|
|
Some(v) => v.clone(),
|
|
}
|
|
}
|
|
|
|
pub fn description(&self) -> String {
|
|
self.description.clone()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_option_serialize() {
|
|
let tests = vec![
|
|
(
|
|
ConfigOption::new("name", Value::String("default".to_string()), "description"),
|
|
json!({
|
|
"name": "name",
|
|
"description":"description",
|
|
"default": "default",
|
|
"type": "string",
|
|
}),
|
|
),
|
|
(
|
|
ConfigOption::new("name", Value::Integer(42), "description"),
|
|
json!({
|
|
"name": "name",
|
|
"description":"description",
|
|
"default": 42,
|
|
"type": "int",
|
|
}),
|
|
),
|
|
(
|
|
ConfigOption::new("name", Value::Boolean(true), "description"),
|
|
json!({
|
|
"name": "name",
|
|
"description":"description",
|
|
"default": true,
|
|
"type": "bool",
|
|
}),
|
|
),
|
|
];
|
|
|
|
for (input, expected) in tests.iter() {
|
|
let res = serde_json::to_value(input).unwrap();
|
|
assert_eq!(&res, expected);
|
|
}
|
|
}
|
|
}
|