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 record;
|
||||
pub mod record_serializer;
|
||||
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