ankiconnect_rs/models/
note.rs1use crate::error::NoteError;
4use crate::models::{FieldMedia, Model};
5use crate::Media;
6use std::collections::{HashMap, HashSet};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub struct NoteId(pub u64);
11
12impl NoteId {
13 pub fn value(&self) -> u64 {
15 self.0
16 }
17}
18
19#[derive(Debug, Clone)]
21pub struct Note {
22 id: Option<NoteId>, model: Model,
24 field_values: HashMap<String, String>,
25 tags: HashSet<String>,
26 media: Vec<FieldMedia>,
27}
28
29impl Note {
30 pub fn new(
32 model: Model,
33 field_values: HashMap<String, String>,
34 tags: HashSet<String>,
35 media: Vec<FieldMedia>,
36 ) -> std::result::Result<Self, NoteError> {
37 for field_name in field_values.keys() {
39 if model.get_field(field_name).is_none() {
40 return Err(NoteError::UnknownField(field_name.to_string()));
41 }
42 }
43
44 for field_media in &media {
46 if model.get_field(&field_media.field).is_none() {
47 return Err(NoteError::UnknownField(field_media.field.clone()));
48 }
49 }
50
51 Ok(Self {
52 id: None,
53 model,
54 field_values,
55 tags,
56 media,
57 })
58 }
59
60 pub fn with_id(
62 id: NoteId,
63 model: Model,
64 field_values: HashMap<String, String>,
65 tags: HashSet<String>,
66 media: Vec<FieldMedia>,
67 ) -> std::result::Result<Self, NoteError> {
68 let mut note = Self::new(model, field_values, tags, media)?;
69 note.id = Some(id);
70 Ok(note)
71 }
72
73 pub fn id(&self) -> Option<NoteId> {
75 self.id
76 }
77
78 pub fn model(&self) -> &Model {
80 &self.model
81 }
82
83 pub fn field_values(&self) -> &HashMap<String, String> {
85 &self.field_values
86 }
87
88 pub fn field_value(&self, field_name: &str) -> Option<&String> {
90 self.field_values.get(field_name)
91 }
92
93 pub fn tags(&self) -> &HashSet<String> {
95 &self.tags
96 }
97
98 pub fn media(&self) -> &[FieldMedia] {
100 &self.media
101 }
102
103 pub fn has_tag(&self, tag: &str) -> bool {
105 self.tags.contains(tag)
106 }
107
108 pub fn update_field(
110 &mut self,
111 field_name: &str,
112 value: String,
113 ) -> std::result::Result<(), NoteError> {
114 if self.model.get_field(field_name).is_none() {
115 return Err(NoteError::UnknownField(field_name.to_string()));
116 }
117 self.field_values.insert(field_name.to_string(), value);
118 Ok(())
119 }
120
121 pub fn add_tag(&mut self, tag: String) {
123 self.tags.insert(tag);
124 }
125
126 pub fn remove_tag(&mut self, tag: &str) -> bool {
128 self.tags.remove(tag)
129 }
130
131 pub fn add_media(
133 &mut self,
134 field_name: &str,
135 media: Media,
136 ) -> std::result::Result<(), NoteError> {
137 if self.model.get_field(field_name).is_none() {
138 return Err(NoteError::UnknownField(field_name.to_string()));
139 }
140
141 self.media.push(FieldMedia {
142 media,
143 field: field_name.to_string(),
144 });
145
146 Ok(())
147 }
148
149 pub fn front_value(&self) -> Option<&String> {
151 self.model
152 .front_field()
153 .and_then(|field| self.field_values.get(field.name()))
154 }
155
156 pub fn back_value(&self) -> Option<&String> {
158 self.model
159 .back_field()
160 .and_then(|field| self.field_values.get(field.name()))
161 }
162}