/
githubmirror
/
thin-provisioning-tools
Обзор
Документация
Войти
/
githubmirror
/
thin-provisioning-tools
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/era/xml.rs
315 строк
9 KB
Ming-Hung Tsai
[build] Update quick-xml to v0.36
10 июл 2024, 19:42
10 июл 2024, 19:42
f584a1b
Код
Авторство
О чём код?
use anyhow::{anyhow, Result}; use quick_xml::events::{BytesEnd, BytesStart, Event}; use quick_xml::{Reader, Writer}; use std::io::{BufRead, BufReader}; use std::io::{Read, Write}; use crate::era::ir::*; use crate::xml::*; //--------------------------------------- pub struct XmlWriter<W: Write> { w: Writer<W>, compact: bool, nr_blocks: u32, emitted_blocks: u32, } impl<W: Write> XmlWriter<W> { pub fn new(w: W, compact: bool) -> XmlWriter<W> { XmlWriter { w: Writer::new_with_indent(w, 0x20, 2), compact, nr_blocks: 0, emitted_blocks: 0, } } } impl<W: Write> MetadataVisitor for XmlWriter<W> { fn superblock_b(&mut self, sb: &Superblock) -> Result<Visit> { let mut elem = BytesStart::new("superblock"); elem.push_attribute(mk_attr(b"uuid", sb.uuid.clone())); elem.push_attribute(mk_attr(b"block_size", sb.block_size)); elem.push_attribute(mk_attr(b"nr_blocks", sb.nr_blocks)); elem.push_attribute(mk_attr(b"current_era", sb.current_era)); self.w.write_event(Event::Start(elem))?; self.nr_blocks = sb.nr_blocks; Ok(Visit::Continue) } fn superblock_e(&mut self) -> Result<Visit> { self.w .write_event(Event::End(BytesEnd::new("superblock")))?; Ok(Visit::Continue) } fn writeset_b(&mut self, ws: &Writeset) -> Result<Visit> { let mut elem = BytesStart::new("writeset"); elem.push_attribute(mk_attr(b"era", ws.era)); elem.push_attribute(mk_attr(b"nr_bits", ws.nr_bits)); self.w.write_event(Event::Start(elem))?; self.emitted_blocks = 0; Ok(Visit::Continue) } fn writeset_e(&mut self) -> Result<Visit> { if !self.compact { for b in self.emitted_blocks..self.nr_blocks { let mut elem = BytesStart::new("bit"); elem.push_attribute(mk_attr(b"block", b)); elem.push_attribute(mk_attr(b"value", "false")); self.w.write_event(Event::Empty(elem))?; } } self.w.write_event(Event::End(BytesEnd::new("writeset")))?; Ok(Visit::Continue) } fn writeset_blocks(&mut self, blocks: &MarkedBlocks) -> Result<Visit> { if self.compact { let mut elem = BytesStart::new("marked"); elem.push_attribute(mk_attr(b"block_begin", blocks.begin)); elem.push_attribute(mk_attr(b"len", blocks.len)); self.w.write_event(Event::Empty(elem))?; } else { for b in self.emitted_blocks..blocks.begin { let mut elem = BytesStart::new("bit"); elem.push_attribute(mk_attr(b"block", b)); elem.push_attribute(mk_attr(b"value", "false")); self.w.write_event(Event::Empty(elem))?; } let end = blocks.begin + blocks.len; for b in blocks.begin..end { let mut elem = BytesStart::new("bit"); elem.push_attribute(mk_attr(b"block", b)); elem.push_attribute(mk_attr(b"value", "true")); self.w.write_event(Event::Empty(elem))?; } self.emitted_blocks = end; } Ok(Visit::Continue) } fn era_b(&mut self) -> Result<Visit> { let elem = BytesStart::new("era_array"); self.w.write_event(Event::Start(elem))?; Ok(Visit::Continue) } fn era_e(&mut self) -> Result<Visit> { self.w.write_event(Event::End(BytesEnd::new("era_array")))?; Ok(Visit::Continue) } fn era(&mut self, era: &Era) -> Result<Visit> { let mut elem = BytesStart::new("era"); elem.push_attribute(mk_attr(b"block", era.block)); elem.push_attribute(mk_attr(b"era", era.era)); self.w.write_event(Event::Empty(elem))?; Ok(Visit::Continue) } fn eof(&mut self) -> Result<Visit> { let w = self.w.get_mut(); w.flush()?; Ok(Visit::Continue) } } //------------------------------------------ fn parse_superblock(e: &BytesStart) -> Result<Superblock> { let tag = "superblock"; let mut uuid: Option<String> = None; let mut block_size: Option<u32> = None; let mut nr_blocks: Option<u32> = None; let mut current_era: Option<u32> = None; for a in e.attributes() { let kv = a.unwrap(); match kv.key.0 { b"uuid" => uuid = Some(string_val(&kv)?), b"block_size" => block_size = Some(u32_val(&kv)?), b"nr_blocks" => nr_blocks = Some(u32_val(&kv)?), b"current_era" => current_era = Some(u32_val(&kv)?), _ => return bad_attr(tag, kv.key.0), } } Ok(Superblock { uuid: check_attr(tag, "uuid", uuid)?, block_size: check_attr(tag, "block_size", block_size)?, nr_blocks: check_attr(tag, "nr_cache_blocks", nr_blocks)?, current_era: check_attr(tag, "current_era", current_era)?, }) } fn parse_writeset(e: &BytesStart) -> Result<Writeset> { let tag = "writeset"; let mut era: Option<u32> = None; let mut nr_bits: Option<u32> = None; for a in e.attributes() { let kv = a.unwrap(); match kv.key.0 { b"era" => era = Some(u32_val(&kv)?), b"nr_bits" => nr_bits = Some(u32_val(&kv)?), _ => return bad_attr(tag, kv.key.0), } } Ok(Writeset { era: check_attr(tag, "era", era)?, nr_bits: check_attr(tag, "nr_bits", nr_bits)?, }) } fn parse_writeset_bit(e: &BytesStart) -> Result<Option<MarkedBlocks>> { let tag = "bit"; let mut block: Option<u32> = None; let mut value: Option<bool> = None; for a in e.attributes() { let kv = a.unwrap(); match kv.key.0 { b"block" => block = Some(u32_val(&kv)?), b"value" => value = Some(bool_val(&kv)?), _ => return bad_attr(tag, kv.key.0), } } check_attr(tag, "block", block)?; check_attr(tag, "value", value)?; if let Some(true) = value { Ok(Some(MarkedBlocks { begin: block.unwrap(), len: 1, })) } else { Ok(None) } } fn parse_writeset_blocks(e: &BytesStart) -> Result<MarkedBlocks> { let tag = "marked"; let mut begin: Option<u32> = None; let mut len: Option<u32> = None; for a in e.attributes() { let kv = a.unwrap(); match kv.key.0 { b"block_begin" => begin = Some(u32_val(&kv)?), b"len" => len = Some(u32_val(&kv)?), _ => return bad_attr(tag, kv.key.0), } } Ok(MarkedBlocks { begin: check_attr(tag, "block_begin", begin)?, len: check_attr(tag, "len", len)?, }) } fn parse_era(e: &BytesStart) -> Result<Era> { let tag = "era"; let mut block: Option<u32> = None; let mut era: Option<u32> = None; for a in e.attributes() { let kv = a.unwrap(); match kv.key.0 { b"block" => block = Some(u32_val(&kv)?), b"era" => era = Some(u32_val(&kv)?), _ => return bad_attr(tag, kv.key.0), } } Ok(Era { block: check_attr(tag, "block", block)?, era: check_attr(tag, "era", era)?, }) } fn handle_event<R, M>(reader: &mut Reader<R>, buf: &mut Vec<u8>, visitor: &mut M) -> Result<Visit> where R: Read + BufRead, M: MetadataVisitor, { match reader.read_event_into(buf) { Ok(Event::Start(ref e)) => match e.name().0 { b"superblock" => visitor.superblock_b(&parse_superblock(e)?), b"writeset" => visitor.writeset_b(&parse_writeset(e)?), b"era_array" => visitor.era_b(), _ => Err(anyhow!( "unknown start tag at byte {}", reader.buffer_position() )), }, Ok(Event::End(ref e)) => match e.name().0 { b"superblock" => visitor.superblock_e(), b"writeset" => visitor.writeset_e(), b"era_array" => visitor.era_e(), _ => Err(anyhow!( "unknown end tag at byte {}", reader.buffer_position() )), }, Ok(Event::Empty(ref e)) => match e.name().0 { b"bit" => { if let Some(b) = parse_writeset_bit(e)? { visitor.writeset_blocks(&b) } else { Ok(Visit::Continue) } } b"marked" => visitor.writeset_blocks(&parse_writeset_blocks(e)?), b"era" => visitor.era(&parse_era(e)?), _ => Err(anyhow!( "unknown empty tag at byte {}", reader.buffer_position() )), }, Ok(Event::Text(_)) => Ok(Visit::Continue), Ok(Event::Comment(_)) => Ok(Visit::Continue), Ok(Event::Eof) => { visitor.eof()?; Ok(Visit::Stop) } Ok(_) => Err(anyhow!( "unsupported element at byte {}", reader.buffer_position() )), Err(e) => Err(anyhow!( "parse error at byte {}: {:?}", reader.buffer_position(), e )), } } pub fn read<R, M>(input: R, visitor: &mut M) -> Result<()> where R: Read, M: MetadataVisitor, { let input = BufReader::new(input); let mut reader = Reader::from_reader(input); reader.config_mut().trim_text(true); let mut buf = Vec::new(); while let Visit::Continue = handle_event(&mut reader, &mut buf, visitor)? {} Ok(()) } //------------------------------------------