rune_modules/
toml.rs

1//! The native `toml` module for the [Rune Language].
2//!
3//! [Rune Language]: https://rune-rs.github.io
4//!
5//! ## Usage
6//!
7//! Add the following to your `Cargo.toml`:
8//!
9//! ```toml
10//! rune-modules = { version = "0.14.1", features = ["toml"] }
11//! ```
12//!
13//! Install it into your context:
14//!
15//! ```rust
16//! let mut context = rune::Context::with_default_modules()?;
17//! context.install(rune_modules::toml::module(true)?)?;
18//! # Ok::<_, rune::support::Error>(())
19//! ```
20//!
21//! Use it in Rune:
22//!
23//! ```rust,ignore
24//! use toml;
25//!
26//! fn main() {
27//!     let data = toml::from_string("[hello]\nworld = 42");
28//!     dbg(data);
29//! }
30//! ```
31
32use rune::alloc::String;
33use rune::runtime::{Bytes, Value};
34use rune::{ContextError, Module};
35
36/// Construct the `toml` module.
37pub fn module(_stdio: bool) -> Result<Module, ContextError> {
38    let mut module = Module::with_crate("toml")?;
39    module.function_meta(from_bytes)?;
40    module.function_meta(from_string)?;
41    module.function_meta(to_string)?;
42    module.function_meta(to_bytes)?;
43    Ok(module)
44}
45
46pub mod de {
47    //! Deserializer types for the toml module.
48
49    use rune::alloc::fmt::TryWrite;
50    use rune::runtime::{Formatter, VmResult};
51    use rune::{vm_write, Any, ContextError, Module};
52
53    pub fn module(_stdio: bool) -> Result<Module, ContextError> {
54        let mut module = Module::with_crate_item("toml", ["de"])?;
55        module.ty::<Error>()?;
56        module.function_meta(Error::display)?;
57        module.function_meta(Error::debug)?;
58        Ok(module)
59    }
60
61    #[derive(Any)]
62    #[rune(item = ::toml::de)]
63    pub(crate) struct Error {
64        pub(crate) error: toml::de::Error,
65    }
66
67    impl Error {
68        #[rune::function(protocol = DISPLAY_FMT)]
69        pub(crate) fn display(&self, f: &mut Formatter) -> VmResult<()> {
70            vm_write!(f, "{}", self.error)
71        }
72
73        #[rune::function(protocol = DEBUG_FMT)]
74        pub(crate) fn debug(&self, f: &mut Formatter) -> VmResult<()> {
75            vm_write!(f, "{:?}", self.error)
76        }
77    }
78
79    impl From<toml::de::Error> for Error {
80        fn from(error: toml::de::Error) -> Self {
81            Self { error }
82        }
83    }
84}
85
86pub mod ser {
87    //! Serializer types for the toml module.
88
89    use rune::alloc::fmt::TryWrite;
90    use rune::runtime::{Formatter, VmResult};
91    use rune::{vm_write, Any, ContextError, Module};
92
93    pub fn module(_stdio: bool) -> Result<Module, ContextError> {
94        let mut module = Module::with_crate_item("toml", ["ser"])?;
95        module.ty::<Error>()?;
96        module.function_meta(Error::display)?;
97        module.function_meta(Error::debug)?;
98        Ok(module)
99    }
100
101    #[derive(Any)]
102    #[rune(item = ::toml::ser)]
103    pub(crate) struct Error {
104        pub(crate) error: toml::ser::Error,
105    }
106
107    impl Error {
108        #[rune::function(protocol = DISPLAY_FMT)]
109        pub(crate) fn display(&self, f: &mut Formatter) -> VmResult<()> {
110            vm_write!(f, "{}", self.error)
111        }
112
113        #[rune::function(protocol = DEBUG_FMT)]
114        pub(crate) fn debug(&self, f: &mut Formatter) -> VmResult<()> {
115            vm_write!(f, "{:?}", self.error)
116        }
117    }
118
119    impl From<toml::ser::Error> for Error {
120        fn from(error: toml::ser::Error) -> Self {
121            Self { error }
122        }
123    }
124}
125
126/// Convert bytes of TOML into a rune value.
127#[rune::function(vm_result)]
128fn from_bytes(bytes: &[u8]) -> Result<Value, Value> {
129    let bytes = match std::str::from_utf8(bytes) {
130        Ok(bytes) => bytes,
131        Err(error) => return Err(rune::to_value(error).vm?),
132    };
133
134    match toml::from_str(bytes).map_err(de::Error::from) {
135        Ok(value) => Ok(value),
136        Err(error) => Err(rune::to_value(error).vm?),
137    }
138}
139
140/// Convert a string of TOML into a rune value.
141#[rune::function]
142fn from_string(string: &str) -> Result<Value, de::Error> {
143    Ok(toml::from_str(string)?)
144}
145
146/// Convert any value to a toml string.
147#[rune::function(vm_result)]
148fn to_string(value: Value) -> Result<String, ser::Error> {
149    Ok(String::try_from(toml::to_string(&value)?).vm?)
150}
151
152/// Convert any value to toml bytes.
153#[rune::function(vm_result)]
154fn to_bytes(value: Value) -> Result<Bytes, ser::Error> {
155    let string = String::try_from(toml::to_string(&value)?).vm?;
156    Ok(Bytes::from_vec(string.into_bytes()))
157}