Skip to main content

boring_parser/
types.rs

1//! 共通型定義
2//!
3//! 複数のDTDバージョンで共通して使用される型
4
5use serde::de::{self, Deserializer, MapAccess, Visitor};
6use serde::{Deserialize, Serialize};
7use std::fmt;
8
9// ============================================================================
10// フリー情報
11// DTD: <!ELEMENT フリー情報 (#PCDATA)>
12// 注: DTDではテキストのみだが、実際のデータでは子要素を含む場合がある
13// ============================================================================
14
15/// フリー情報: テキストのみならSome(String)、子要素があればNone
16#[derive(Debug, Serialize, Default, Clone)]
17pub struct FreeInfo(pub Option<String>);
18
19impl<'de> Deserialize<'de> for FreeInfo {
20    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
21    where
22        D: Deserializer<'de>,
23    {
24        deserializer.deserialize_any(FreeInfoVisitor)
25    }
26}
27
28struct FreeInfoVisitor;
29
30impl<'de> Visitor<'de> for FreeInfoVisitor {
31    type Value = FreeInfo;
32
33    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
34        formatter.write_str("a string or any element (which will be skipped)")
35    }
36
37    // テキストの場合
38    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
39    where
40        E: de::Error,
41    {
42        let trimmed = value.trim();
43        Ok(FreeInfo((!trimmed.is_empty()).then(|| trimmed.to_string())))
44    }
45
46    // 子要素がある場合はmapとして来る - スキップしてNoneを返す
47    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
48    where
49        A: MapAccess<'de>,
50    {
51        while map.next_entry::<de::IgnoredAny, de::IgnoredAny>()?.is_some() {}
52        Ok(FreeInfo(None))
53    }
54}