hwp/hwp/doc_info/
bin_data.rs1use byteorder::{LittleEndian, ReadBytesExt};
2use num::FromPrimitive;
3use num_derive::FromPrimitive;
4
5use crate::hwp::{
6 header::Header,
7 record::{reader::RecordReader, tags::DocInfoRecord, FromRecordCursor, RecordCursor},
8 utils::bits::get_value_range,
9 version::Version,
10};
11
12#[derive(Debug)]
13pub struct BinData {
14 pub properties: BinDataProperties,
15 pub absolute_path: Option<String>,
16 pub relative_path: Option<String>,
17 pub id: Option<u16>,
18 pub extension: Option<String>,
19}
20
21impl BinData {
22 pub fn cfb_file_name(&self) -> Option<String> {
23 if self.properties.kind != BinDataKind::Embedding {
24 return None;
25 }
26
27 let mut extension = self.extension.clone().unwrap();
28 extension.make_ascii_lowercase();
29
30 let id = self.id.unwrap();
31
32 Some(format!("BIN{:0>4X}.{extension}", id))
33 }
34
35 pub fn compressed(&self, header: &Header) -> bool {
36 match self.properties.compress_mode {
37 CompressMode::Default => header.flags.compressed,
38 CompressMode::Compress => true,
39 _ => false,
40 }
41 }
42}
43
44impl FromRecordCursor for BinData {
45 fn from_record_cursor(cursor: &mut RecordCursor, _: &Version) -> Self {
46 let record = cursor.current();
47
48 assert_eq!(
49 record.tag_id,
50 DocInfoRecord::HWPTAG_BIN_DATA as u32,
51 "올바르지 않은 정보"
52 );
53
54 let mut data = record.get_data_reader();
55 let properties = data.read_u16::<LittleEndian>().unwrap();
56 let properties = BinDataProperties::from_bits(properties);
57
58 let absolute_path = if properties.kind == BinDataKind::Link {
59 Some(data.read_string::<LittleEndian>().unwrap())
60 } else {
61 None
62 };
63
64 let relative_path = if properties.kind == BinDataKind::Link {
65 Some(data.read_string::<LittleEndian>().unwrap())
66 } else {
67 None
68 };
69
70 let id = if properties.kind == BinDataKind::Embedding
71 || properties.kind == BinDataKind::Storage
72 {
73 Some(data.read_u16::<LittleEndian>().unwrap())
74 } else {
75 None
76 };
77
78 let extension = if properties.kind == BinDataKind::Embedding {
79 Some(data.read_string::<LittleEndian>().unwrap())
80 } else {
81 None
82 };
83
84 Self {
85 properties,
86 absolute_path,
87 relative_path,
88 id,
89 extension,
90 }
91 }
92}
93
94#[repr(u8)]
95#[derive(Debug, PartialEq, Eq, FromPrimitive)]
96pub enum BinDataKind {
97 Link,
99 Embedding,
101 Storage,
103}
104
105#[repr(u8)]
106#[derive(Debug, PartialEq, Eq, FromPrimitive)]
107pub enum CompressMode {
108 Default,
110 Compress,
112 None,
114}
115
116#[repr(u8)]
117#[derive(Debug, PartialEq, Eq, FromPrimitive)]
118pub enum BinDataStatus {
119 Initial,
121 Success,
123 Failed,
125 Ignored,
127}
128
129#[derive(Debug)]
130pub struct BinDataProperties {
131 pub kind: BinDataKind,
133 pub compress_mode: CompressMode,
135 pub status: BinDataStatus,
137}
138
139impl BinDataProperties {
140 pub fn from_bits(bits: u16) -> Self {
141 Self {
142 kind: BinDataKind::from_u16(get_value_range(bits, 0, 3)).unwrap(),
143 compress_mode: CompressMode::from_u16(get_value_range(bits, 4, 5)).unwrap(),
144 status: BinDataStatus::from_u16(get_value_range(bits, 8, 9)).unwrap(),
145 }
146 }
147}