Replace ALL of the nu stuff with embed-nu
parent
8d37f60cd7
commit
fd97b535df
@ -1,232 +0,0 @@
|
|||||||
#![allow(unused)]
|
|
||||||
use std::{
|
|
||||||
collections::HashMap,
|
|
||||||
mem,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
|
||||||
|
|
||||||
use nu_cli::gather_parent_env_vars;
|
|
||||||
use tokio::fs;
|
|
||||||
|
|
||||||
use miette::IntoDiagnostic;
|
|
||||||
use nu_protocol::{
|
|
||||||
ast::{Argument, Block, Call, Expr, Expression, Pipeline},
|
|
||||||
engine::{EngineState, Stack, StateDelta, StateWorkingSet},
|
|
||||||
DeclId, PipelineData, Signature, Span, Type, Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::error::{AppError, AppResult};
|
|
||||||
|
|
||||||
use super::record::RecordValue;
|
|
||||||
|
|
||||||
/// An executor for nu scripts
|
|
||||||
pub struct NuExecutor {
|
|
||||||
script_path: PathBuf,
|
|
||||||
args: Vec<RecordValue>,
|
|
||||||
global_vars: HashMap<String, RecordValue>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NuExecutor {
|
|
||||||
pub fn new<P: AsRef<Path>>(script_path: P) -> Self {
|
|
||||||
Self {
|
|
||||||
script_path: script_path.as_ref().to_owned(),
|
|
||||||
args: Vec::new(),
|
|
||||||
global_vars: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_arg<A: Into<RecordValue>>(&mut self, arg: A) -> &mut Self {
|
|
||||||
self.args.push(arg.into());
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_args<A: Into<RecordValue>, I: IntoIterator<Item = A>>(
|
|
||||||
&mut self,
|
|
||||||
args: I,
|
|
||||||
) -> &mut Self {
|
|
||||||
let mut args = args.into_iter().map(|a| a.into()).collect::<Vec<_>>();
|
|
||||||
self.args.append(&mut args);
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds a global variable to the executor which can
|
|
||||||
/// be accessed from within the script
|
|
||||||
pub fn add_global_var<S: ToString, V: Into<RecordValue>>(
|
|
||||||
&mut self,
|
|
||||||
name: S,
|
|
||||||
value: V,
|
|
||||||
) -> &mut Self {
|
|
||||||
self.global_vars.insert(name.to_string(), value.into());
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds multiple global variables
|
|
||||||
pub fn add_global_vars<S: ToString, R: Into<RecordValue>, I: IntoIterator<Item = (S, R)>>(
|
|
||||||
&mut self,
|
|
||||||
vars: I,
|
|
||||||
) -> &mut Self {
|
|
||||||
self.global_vars
|
|
||||||
.extend(&mut vars.into_iter().map(|(k, v)| (k.to_string(), v.into())));
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Executes the given script file in a clean nu context.
|
|
||||||
#[tracing::instrument(level = "trace", skip_all)]
|
|
||||||
pub async fn execute(&mut self) -> AppResult<()> {
|
|
||||||
let mut engine_state = nu_command::create_default_context();
|
|
||||||
let mut stack = nu_protocol::engine::Stack::new();
|
|
||||||
let init_cwd = nu_cli::get_init_cwd();
|
|
||||||
gather_parent_env_vars(&mut engine_state, &init_cwd);
|
|
||||||
nu_engine::convert_env_values(&mut engine_state, &stack);
|
|
||||||
|
|
||||||
let vars = mem::take(&mut self.global_vars);
|
|
||||||
let vars = vars
|
|
||||||
.into_iter()
|
|
||||||
.map(|(k, v)| (k, v.into_protocol_value()))
|
|
||||||
.collect::<HashMap<_, _>>();
|
|
||||||
|
|
||||||
add_variables_to_state(vars, &mut engine_state, &mut stack);
|
|
||||||
let (block, main_id) = read_script_file(&self.script_path, &mut engine_state).await?;
|
|
||||||
|
|
||||||
// put everything the script defines into scope
|
|
||||||
nu_engine::eval_block(
|
|
||||||
&engine_state,
|
|
||||||
&mut stack,
|
|
||||||
&block,
|
|
||||||
empty_pipeline(),
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.into_diagnostic()?;
|
|
||||||
|
|
||||||
let args = mem::take(&mut self.args);
|
|
||||||
|
|
||||||
// block in a different thread to be able to execute scripts in parallel
|
|
||||||
tokio::task::spawn_blocking(move || {
|
|
||||||
// create a call to the main method wit the given arguments and execute it
|
|
||||||
let call_block = create_call(main_id, args);
|
|
||||||
|
|
||||||
let data = nu_engine::eval_block(
|
|
||||||
&engine_state,
|
|
||||||
&mut stack,
|
|
||||||
&call_block,
|
|
||||||
empty_pipeline(),
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
)?;
|
|
||||||
// the last print is returned as the result pipeline of the script so
|
|
||||||
// we need to print it manually
|
|
||||||
data.print(&mut engine_state, &mut stack, false, true);
|
|
||||||
|
|
||||||
AppResult::Ok(())
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap()?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds variables to the nu engine state
|
|
||||||
/// Note: Calling this function multiple times will override other variables
|
|
||||||
#[tracing::instrument(level = "trace", skip(state, stack))]
|
|
||||||
fn add_variables_to_state(
|
|
||||||
vars: HashMap<String, Value>,
|
|
||||||
state: &mut EngineState,
|
|
||||||
stack: &mut Stack,
|
|
||||||
) {
|
|
||||||
let state2 = nu_command::create_default_context();
|
|
||||||
let mut working_set = StateWorkingSet::new(&state2);
|
|
||||||
vars.into_iter()
|
|
||||||
.map(|(name, value)| {
|
|
||||||
(
|
|
||||||
working_set.add_variable(
|
|
||||||
name.as_bytes().to_vec(),
|
|
||||||
Span::new(0, 0),
|
|
||||||
nu_protocol::Type::String,
|
|
||||||
),
|
|
||||||
value,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.for_each(|(var_id, value)| stack.add_var(var_id, value));
|
|
||||||
state.merge_delta(working_set.render());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reads the nu script file and
|
|
||||||
/// returns its root block
|
|
||||||
#[tracing::instrument(level = "trace", skip(engine_state))]
|
|
||||||
async fn read_script_file(
|
|
||||||
path: &Path,
|
|
||||||
engine_state: &mut EngineState,
|
|
||||||
) -> AppResult<(Block, DeclId)> {
|
|
||||||
let script_contents = fs::read(&path).await.into_diagnostic()?;
|
|
||||||
let string_path = path.to_string_lossy().into_owned();
|
|
||||||
// parse the source file
|
|
||||||
let (block, working_set) = parse_nu(engine_state, &script_contents, Some(&string_path))?;
|
|
||||||
// check if a main method exists in the block
|
|
||||||
if let Some(decl_id) = working_set.find_decl(b"main", &Type::Block) {
|
|
||||||
let delta = working_set.render();
|
|
||||||
engine_state.merge_delta(delta);
|
|
||||||
|
|
||||||
Ok((block, decl_id))
|
|
||||||
} else {
|
|
||||||
Err(AppError::MissingMain(PathBuf::from(path)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parses a nu script
|
|
||||||
#[tracing::instrument(level = "trace", skip_all)]
|
|
||||||
fn parse_nu<'a>(
|
|
||||||
engine_state: &'a mut EngineState,
|
|
||||||
script: &[u8],
|
|
||||||
script_path: Option<&str>,
|
|
||||||
) -> AppResult<(Block, StateWorkingSet<'a>)> {
|
|
||||||
let mut working_set = StateWorkingSet::new(engine_state);
|
|
||||||
let (block, err) = nu_parser::parse(&mut working_set, script_path, script, false, &[]);
|
|
||||||
|
|
||||||
if let Some(err) = err {
|
|
||||||
Err(AppError::from(err))
|
|
||||||
} else {
|
|
||||||
Ok((block, working_set))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a call nu expression with the given main block declaration ID
|
|
||||||
/// and arguments in the form of record values
|
|
||||||
#[tracing::instrument(level = "trace")]
|
|
||||||
fn create_call(decl_id: DeclId, args: Vec<RecordValue>) -> Block {
|
|
||||||
let args = args
|
|
||||||
.into_iter()
|
|
||||||
.map(|a| Argument::Positional(a.into_expression()))
|
|
||||||
.collect();
|
|
||||||
let call = Call {
|
|
||||||
decl_id,
|
|
||||||
head: Span::new(0, 0),
|
|
||||||
arguments: args,
|
|
||||||
redirect_stdout: true,
|
|
||||||
redirect_stderr: false,
|
|
||||||
};
|
|
||||||
let pipeline = Pipeline {
|
|
||||||
expressions: vec![Expression {
|
|
||||||
expr: Expr::Call(Box::new(call)),
|
|
||||||
span: Span::new(0, 0),
|
|
||||||
ty: Type::Any,
|
|
||||||
custom_completion: None,
|
|
||||||
}],
|
|
||||||
};
|
|
||||||
Block {
|
|
||||||
signature: Box::new(Signature::build("Call to main")),
|
|
||||||
pipelines: vec![pipeline],
|
|
||||||
captures: Vec::new(),
|
|
||||||
redirect_env: false,
|
|
||||||
span: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn empty_pipeline() -> PipelineData {
|
|
||||||
PipelineData::new(Span::new(0, 0))
|
|
||||||
}
|
|
@ -1,5 +1,2 @@
|
|||||||
pub mod executor;
|
|
||||||
pub mod loader;
|
pub mod loader;
|
||||||
pub mod record;
|
|
||||||
pub mod record_serializer;
|
|
||||||
pub mod script;
|
pub mod script;
|
||||||
|
@ -1,190 +0,0 @@
|
|||||||
use std::{borrow::Cow, collections::HashMap};
|
|
||||||
|
|
||||||
use nu_protocol::{
|
|
||||||
ast::{Expr, Expression},
|
|
||||||
Span, Type, Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum RecordValue {
|
|
||||||
Int(i64),
|
|
||||||
Float(f64),
|
|
||||||
String(String),
|
|
||||||
Bytes(Vec<u8>),
|
|
||||||
Boolean(bool),
|
|
||||||
Null,
|
|
||||||
Map(Vec<(RecordValue, RecordValue)>),
|
|
||||||
List(Vec<RecordValue>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RecordValue {
|
|
||||||
/// Creates an expresion for this value
|
|
||||||
pub fn into_expr(self) -> Expr {
|
|
||||||
match self {
|
|
||||||
RecordValue::Int(i) => Expr::Int(i),
|
|
||||||
RecordValue::Float(f) => Expr::Float(f),
|
|
||||||
RecordValue::String(s) => Expr::String(s),
|
|
||||||
RecordValue::Boolean(b) => Expr::Bool(b),
|
|
||||||
RecordValue::Null => Expr::Nothing,
|
|
||||||
RecordValue::Map(m) => Expr::Record(
|
|
||||||
m.into_iter()
|
|
||||||
.map(|(k, v)| (k.into_expression(), v.into_expression()))
|
|
||||||
.collect(),
|
|
||||||
),
|
|
||||||
RecordValue::List(l) => {
|
|
||||||
Expr::List(l.into_iter().map(RecordValue::into_expression).collect())
|
|
||||||
}
|
|
||||||
RecordValue::Bytes(b) => Expr::Binary(b),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new wrapped expression for this value
|
|
||||||
pub fn into_expression(self) -> Expression {
|
|
||||||
let nu_type = self.get_type();
|
|
||||||
let expr = self.into_expr();
|
|
||||||
|
|
||||||
Expression {
|
|
||||||
expr,
|
|
||||||
span: Span::new(0, 0),
|
|
||||||
ty: nu_type,
|
|
||||||
custom_completion: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a nu protocol value from this value
|
|
||||||
pub fn into_protocol_value(self) -> Value {
|
|
||||||
let span = Span::new(0, 0);
|
|
||||||
|
|
||||||
match self {
|
|
||||||
RecordValue::Int(val) => Value::Int { val, span },
|
|
||||||
RecordValue::Float(val) => Value::Float { val, span },
|
|
||||||
RecordValue::String(val) => Value::String { val, span },
|
|
||||||
RecordValue::Bytes(val) => Value::Binary { val, span },
|
|
||||||
RecordValue::Boolean(val) => Value::Bool { val, span },
|
|
||||||
RecordValue::Null => Value::Nothing { span },
|
|
||||||
RecordValue::Map(m) => {
|
|
||||||
let mut cols = Vec::new();
|
|
||||||
let mut vals = Vec::new();
|
|
||||||
for (key, val) in m {
|
|
||||||
cols.push(key.to_string());
|
|
||||||
vals.push(val.into_protocol_value());
|
|
||||||
}
|
|
||||||
Value::Record { cols, vals, span }
|
|
||||||
}
|
|
||||||
RecordValue::List(l) => Value::List {
|
|
||||||
vals: l
|
|
||||||
.into_iter()
|
|
||||||
.map(RecordValue::into_protocol_value)
|
|
||||||
.collect(),
|
|
||||||
span,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the type of this value
|
|
||||||
fn get_type(&self) -> Type {
|
|
||||||
match &self {
|
|
||||||
RecordValue::Int(_) => Type::Int,
|
|
||||||
RecordValue::Float(_) => Type::Float,
|
|
||||||
RecordValue::String(_) => Type::String,
|
|
||||||
RecordValue::Boolean(_) => Type::Bool,
|
|
||||||
RecordValue::Null => Type::Nothing,
|
|
||||||
RecordValue::Map(m) => {
|
|
||||||
let type_map = m
|
|
||||||
.iter()
|
|
||||||
.map(|(k, v)| (k.to_string(), v.get_type()))
|
|
||||||
.collect();
|
|
||||||
Type::Record(type_map)
|
|
||||||
}
|
|
||||||
RecordValue::List(l) => {
|
|
||||||
let list_type = if let Some(first) = l.first() {
|
|
||||||
first.get_type()
|
|
||||||
} else {
|
|
||||||
Type::Nothing
|
|
||||||
};
|
|
||||||
Type::List(Box::new(list_type))
|
|
||||||
}
|
|
||||||
RecordValue::Bytes(_) => Type::Binary,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToString for RecordValue {
|
|
||||||
fn to_string(&self) -> String {
|
|
||||||
match self {
|
|
||||||
RecordValue::Int(i) => i.to_string(),
|
|
||||||
RecordValue::Float(f) => f.to_string(),
|
|
||||||
RecordValue::String(s) => s.clone(),
|
|
||||||
RecordValue::Boolean(b) => b.to_string(),
|
|
||||||
RecordValue::Null => String::new(),
|
|
||||||
RecordValue::Map(_) => String::new(),
|
|
||||||
RecordValue::List(_) => String::new(),
|
|
||||||
RecordValue::Bytes(_) => String::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<i64> for RecordValue {
|
|
||||||
fn from(num: i64) -> Self {
|
|
||||||
Self::Int(num)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<f64> for RecordValue {
|
|
||||||
fn from(num: f64) -> Self {
|
|
||||||
Self::Float(num)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<String> for RecordValue {
|
|
||||||
fn from(s: String) -> Self {
|
|
||||||
Self::String(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<Cow<'a, str>> for RecordValue {
|
|
||||||
fn from(s: Cow<'a, str>) -> Self {
|
|
||||||
Self::String(s.into_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for RecordValue {
|
|
||||||
fn from(s: &str) -> Self {
|
|
||||||
Self::String(s.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<bool> for RecordValue {
|
|
||||||
fn from(b: bool) -> Self {
|
|
||||||
Self::Boolean(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Into<RecordValue>> From<Option<T>> for RecordValue {
|
|
||||||
fn from(opt: Option<T>) -> Self {
|
|
||||||
match opt {
|
|
||||||
Some(val) => val.into(),
|
|
||||||
None => Self::Null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T1: Into<RecordValue>, T2: Into<RecordValue>> From<HashMap<T1, T2>> for RecordValue {
|
|
||||||
fn from(map: HashMap<T1, T2>) -> Self {
|
|
||||||
let map = map.into_iter().map(|(k, v)| (k.into(), v.into())).collect();
|
|
||||||
Self::Map(map)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Into<RecordValue>> From<Vec<T>> for RecordValue {
|
|
||||||
fn from(list: Vec<T>) -> Self {
|
|
||||||
let list = list.into_iter().map(|l| l.into()).collect();
|
|
||||||
Self::List(list)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Vec<u8>> for RecordValue {
|
|
||||||
fn from(b: Vec<u8>) -> Self {
|
|
||||||
Self::Bytes(b)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,444 +0,0 @@
|
|||||||
use std::{collections::HashMap, mem};
|
|
||||||
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
use super::record::RecordValue;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct RecordSerializer {
|
|
||||||
list_serializer: Option<RecordListSerializer>,
|
|
||||||
map_serializer: Option<RecordMapSerializer>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct RecordListSerializer {
|
|
||||||
serializer: Option<Box<RecordSerializer>>,
|
|
||||||
entries: Vec<RecordValue>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct RecordMapSerializer {
|
|
||||||
serializer: Option<Box<RecordSerializer>>,
|
|
||||||
last_key: Option<RecordValue>,
|
|
||||||
entries: Vec<(RecordValue, RecordValue)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RecordSerializer {
|
|
||||||
pub fn list_serializer(&mut self, cap: Option<usize>) -> &mut RecordListSerializer {
|
|
||||||
if self.list_serializer.is_none() {
|
|
||||||
self.list_serializer = Some(RecordListSerializer::with_capacity_opt(cap));
|
|
||||||
}
|
|
||||||
self.list_serializer.as_mut().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn map_serializer(&mut self, cap: Option<usize>) -> &mut RecordMapSerializer {
|
|
||||||
if self.map_serializer.is_none() {
|
|
||||||
self.map_serializer = Some(RecordMapSerializer::with_capacity_opt(cap));
|
|
||||||
}
|
|
||||||
self.map_serializer.as_mut().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RecordListSerializer {
|
|
||||||
pub fn with_capacity(capacity: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
entries: Vec::with_capacity(capacity),
|
|
||||||
serializer: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_capacity_opt(capacity: Option<usize>) -> Self {
|
|
||||||
match capacity {
|
|
||||||
Some(cap) => Self::with_capacity(cap),
|
|
||||||
None => Self::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn serializer(&mut self) -> &mut RecordSerializer {
|
|
||||||
if self.serializer.is_none() {
|
|
||||||
self.serializer = Some(Box::new(RecordSerializer::default()));
|
|
||||||
}
|
|
||||||
self.serializer.as_mut().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RecordMapSerializer {
|
|
||||||
pub fn with_capacity(capacity: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
last_key: None,
|
|
||||||
entries: Vec::with_capacity(capacity),
|
|
||||||
serializer: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_capacity_opt(capacity: Option<usize>) -> Self {
|
|
||||||
match capacity {
|
|
||||||
Some(cap) => Self::with_capacity(cap),
|
|
||||||
None => Self::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn serializer(&mut self) -> &mut RecordSerializer {
|
|
||||||
if self.serializer.is_none() {
|
|
||||||
self.serializer = Some(Box::new(RecordSerializer::default()));
|
|
||||||
}
|
|
||||||
self.serializer.as_mut().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum RecordSerError {
|
|
||||||
#[error("{0}")]
|
|
||||||
Msg(String),
|
|
||||||
|
|
||||||
#[error("Encountered map value before map key")]
|
|
||||||
ValueBeforeKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl serde::ser::Error for RecordSerError {
|
|
||||||
fn custom<T>(msg: T) -> Self
|
|
||||||
where
|
|
||||||
T: std::fmt::Display,
|
|
||||||
{
|
|
||||||
Self::Msg(msg.to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> serde::ser::Serializer for &'a mut RecordSerializer {
|
|
||||||
type Ok = RecordValue;
|
|
||||||
|
|
||||||
type Error = RecordSerError;
|
|
||||||
|
|
||||||
type SerializeSeq = &'a mut RecordListSerializer;
|
|
||||||
|
|
||||||
type SerializeTuple = &'a mut RecordListSerializer;
|
|
||||||
|
|
||||||
type SerializeTupleStruct = &'a mut RecordListSerializer;
|
|
||||||
|
|
||||||
type SerializeTupleVariant = &'a mut RecordListSerializer;
|
|
||||||
|
|
||||||
type SerializeMap = &'a mut RecordMapSerializer;
|
|
||||||
|
|
||||||
type SerializeStruct = &'a mut RecordMapSerializer;
|
|
||||||
|
|
||||||
type SerializeStructVariant = &'a mut RecordMapSerializer;
|
|
||||||
|
|
||||||
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(v.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok((v as i64).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok((v as i64).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok((v as i64).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(v.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok((v as i64).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok((v as i64).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok((v as i64).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok((v as i64).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok((v as f64).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(v.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(v.to_string().into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(v.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(v.to_vec().into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(RecordValue::Null)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
|
||||||
where
|
|
||||||
T: serde::Serialize,
|
|
||||||
{
|
|
||||||
value.serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.serialize_none()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.serialize_unit()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit_variant(
|
|
||||||
self,
|
|
||||||
_name: &'static str,
|
|
||||||
_variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.serialize_str(variant)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_newtype_struct<T: ?Sized>(
|
|
||||||
self,
|
|
||||||
_name: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<Self::Ok, Self::Error>
|
|
||||||
where
|
|
||||||
T: serde::Serialize,
|
|
||||||
{
|
|
||||||
value.serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_newtype_variant<T: ?Sized>(
|
|
||||||
self,
|
|
||||||
_name: &'static str,
|
|
||||||
_variant_index: u32,
|
|
||||||
variant: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<Self::Ok, Self::Error>
|
|
||||||
where
|
|
||||||
T: serde::Serialize,
|
|
||||||
{
|
|
||||||
let mut map = HashMap::new();
|
|
||||||
map.insert(variant.to_string(), value.serialize(self)?);
|
|
||||||
Ok(map.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
|
||||||
Ok(self.list_serializer(len))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
|
|
||||||
Ok(self.list_serializer(Some(len)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple_struct(
|
|
||||||
self,
|
|
||||||
_name: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
|
||||||
Ok(self.list_serializer(Some(len)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple_variant(
|
|
||||||
self,
|
|
||||||
_name: &'static str,
|
|
||||||
_variant_index: u32,
|
|
||||||
_variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
|
||||||
Ok(self.list_serializer(Some(len)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
|
||||||
Ok(self.map_serializer(len))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_struct(
|
|
||||||
self,
|
|
||||||
_name: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeStruct, Self::Error> {
|
|
||||||
Ok(self.map_serializer(Some(len)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_struct_variant(
|
|
||||||
self,
|
|
||||||
_name: &'static str,
|
|
||||||
_variant_index: u32,
|
|
||||||
_variant: &'static str,
|
|
||||||
len: usize,
|
|
||||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
|
||||||
Ok(self.map_serializer(Some(len)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> serde::ser::SerializeTuple for &'a mut RecordListSerializer {
|
|
||||||
type Ok = RecordValue;
|
|
||||||
|
|
||||||
type Error = RecordSerError;
|
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: serde::Serialize,
|
|
||||||
{
|
|
||||||
let val = value.serialize(self.serializer())?;
|
|
||||||
self.entries.push(val);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(mem::take(&mut self.entries).into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> serde::ser::SerializeSeq for &'a mut RecordListSerializer {
|
|
||||||
type Ok = RecordValue;
|
|
||||||
|
|
||||||
type Error = RecordSerError;
|
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: serde::Serialize,
|
|
||||||
{
|
|
||||||
let val = value.serialize(self.serializer())?;
|
|
||||||
self.entries.push(val);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(mem::take(&mut self.entries).into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> serde::ser::SerializeTupleStruct for &'a mut RecordListSerializer {
|
|
||||||
type Ok = RecordValue;
|
|
||||||
|
|
||||||
type Error = RecordSerError;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: serde::Serialize,
|
|
||||||
{
|
|
||||||
let val = value.serialize(self.serializer())?;
|
|
||||||
self.entries.push(val);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(mem::take(&mut self.entries).into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> serde::ser::SerializeTupleVariant for &'a mut RecordListSerializer {
|
|
||||||
type Ok = RecordValue;
|
|
||||||
|
|
||||||
type Error = RecordSerError;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: serde::Serialize,
|
|
||||||
{
|
|
||||||
let val = value.serialize(self.serializer())?;
|
|
||||||
self.entries.push(val);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(mem::take(&mut self.entries).into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> serde::ser::SerializeMap for &'a mut RecordMapSerializer {
|
|
||||||
type Ok = RecordValue;
|
|
||||||
|
|
||||||
type Error = RecordSerError;
|
|
||||||
|
|
||||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: serde::Serialize,
|
|
||||||
{
|
|
||||||
let val = key.serialize(self.serializer())?;
|
|
||||||
self.last_key = Some(val);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: serde::Serialize,
|
|
||||||
{
|
|
||||||
if let Some(last_key) = self.last_key.take() {
|
|
||||||
let val = value.serialize(self.serializer())?;
|
|
||||||
self.entries.push((last_key, val));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(RecordSerError::ValueBeforeKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(RecordValue::Map(mem::take(&mut self.entries)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> serde::ser::SerializeStruct for &'a mut RecordMapSerializer {
|
|
||||||
type Ok = RecordValue;
|
|
||||||
|
|
||||||
type Error = RecordSerError;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(
|
|
||||||
&mut self,
|
|
||||||
key: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: serde::Serialize,
|
|
||||||
{
|
|
||||||
let val = value.serialize(self.serializer())?;
|
|
||||||
self.entries.push((key.into(), val));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(RecordValue::Map(mem::take(&mut self.entries)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> serde::ser::SerializeStructVariant for &'a mut RecordMapSerializer {
|
|
||||||
type Ok = RecordValue;
|
|
||||||
|
|
||||||
type Error = RecordSerError;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(
|
|
||||||
&mut self,
|
|
||||||
key: &'static str,
|
|
||||||
value: &T,
|
|
||||||
) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
T: serde::Serialize,
|
|
||||||
{
|
|
||||||
let val = value.serialize(self.serializer())?;
|
|
||||||
self.entries.push((key.into(), val));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(RecordValue::Map(mem::take(&mut self.entries)))
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue