gpt4 book ai didi

rust - 我怎样才能让 Serde 在反序列化期间从 arena 分配字符串?

转载 作者:行者123 更新时间:2023-11-29 08:00:16 24 4
gpt4 key购买 nike

我有一个包含字符串字段的结构。我想控制字符串的内存分配方式。特别是,我想使用类似 copy_arena 的方式来分配它们。 .

也许我可以制作自定义 ArenaString 类型,但我不知道如何将对 Arena 的引用获取到反序列化代码中,并假设这是可能的,那么我将不得不处理竞技场生命周期,对吧?

最佳答案

这是使用 serde::de::DeserializeSeed 的一种可能实现方式将竞技场分配器暴露给反序列化代码。

在更复杂的用例中,您可能希望编写一个过程宏来生成此类 impl。


#[macro_use]
extern crate serde_derive;

extern crate copy_arena;
extern crate serde;
extern crate serde_json;

use std::fmt;
use std::marker::PhantomData;
use std::str;

use serde::de::{self, DeserializeSeed, Deserializer, MapAccess, Visitor};

use copy_arena::{Allocator, Arena};

#[derive(Debug)]
struct Jason<'a> {
one: &'a str,
two: &'a str,
}

struct ArenaSeed<'a, T> {
allocator: Allocator<'a>,
marker: PhantomData<fn() -> T>,
}

impl<'a, T> ArenaSeed<'a, T> {
fn new(arena: &'a mut Arena) -> Self {
ArenaSeed {
allocator: arena.allocator(),
marker: PhantomData,
}
}

fn alloc_string(&mut self, owned: String) -> &'a str {
let slice = self.allocator.alloc_slice(owned.as_bytes());
// We know the bytes are valid UTF-8.
str::from_utf8(slice).unwrap()
}
}

impl<'de, 'a> DeserializeSeed<'de> for ArenaSeed<'a, Jason<'a>> {
type Value = Jason<'a>;

fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
static FIELDS: &[&str] = &["one", "two"];
deserializer.deserialize_struct("Jason", FIELDS, self)
}
}

impl<'de, 'a> Visitor<'de> for ArenaSeed<'a, Jason<'a>> {
type Value = Jason<'a>;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct Jason")
}

fn visit_map<A>(mut self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
#[derive(Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum Field { One, Two }

let mut one = None;
let mut two = None;
while let Some(key) = map.next_key()? {
match key {
Field::One => {
if one.is_some() {
return Err(de::Error::duplicate_field("one"));
}
one = Some(self.alloc_string(map.next_value()?));
}
Field::Two => {
if two.is_some() {
return Err(de::Error::duplicate_field("two"));
}
two = Some(self.alloc_string(map.next_value()?));
}
}
}
let one = one.ok_or_else(|| de::Error::missing_field("one"))?;
let two = two.ok_or_else(|| de::Error::missing_field("two"))?;
Ok(Jason { one, two })
}
}

fn main() {
let j = r#" {"one": "I", "two": "II"} "#;

let mut arena = Arena::new();
let seed = ArenaSeed::new(&mut arena);
let mut de = serde_json::Deserializer::from_str(j);
let jason: Jason = seed.deserialize(&mut de).unwrap();
println!("{:?}", jason);
}

如果 arena 分配不是一个严格的要求,而您只需要在大量反序列化对象之间分摊字符串分配的成本,Deserialize::deserialize_in_place 是一个更简洁的选择。

// [dependencies]
// serde = "1.0"
// serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
// serde_json = "1.0"

#[macro_use]
extern crate serde_derive;

extern crate serde;
extern crate serde_json;

use serde::Deserialize;

#[derive(Deserialize, Debug)]
struct Jason {
one: String,
two: String,
}

fn main() {
let j = r#" {"one": "I", "two": "II"} "#;

// Allocate some Strings during deserialization.
let mut de = serde_json::Deserializer::from_str(j);
let mut jason = Jason::deserialize(&mut de).unwrap();
println!("{:?} {:p} {:p}", jason, jason.one.as_str(), jason.two.as_str());

// Reuse the same String allocations for some new data.
// As long as the strings in the new datum are at most as long as the
// previous datum, the strings do not need to be reallocated and will
// remain at the same memory address.
let mut de = serde_json::Deserializer::from_str(j);
Jason::deserialize_in_place(&mut de, &mut jason).unwrap();
println!("{:?} {:p} {:p}", jason, jason.one.as_str(), jason.two.as_str());

// Do not reuse the string allocations.
// The strings here will not be at the same address as above.
let mut de = serde_json::Deserializer::from_str(j);
let jason = Jason::deserialize(&mut de).unwrap();
println!("{:?} {:p} {:p}", jason, jason.one.as_str(), jason.two.as_str());
}

关于rust - 我怎样才能让 Serde 在反序列化期间从 arena 分配字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51988630/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com