ffbm/types.rs
1//! Core types for bookmark representation.
2
3use std::path::PathBuf;
4
5use serde::{Deserialize, Serialize};
6
7/// A Firefox profile discovered from Profile Groups.
8#[derive(Debug, Clone)]
9pub struct Profile {
10 /// The display name of the profile.
11 pub name: String,
12 /// Absolute path to the profile directory.
13 pub path: PathBuf,
14}
15
16/// A bookmark entry.
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct Bookmark {
19 /// The URL of the bookmark.
20 pub url: String,
21 /// The display title.
22 pub title: String,
23 /// Tags associated with this bookmark.
24 #[serde(default, skip_serializing_if = "Vec::is_empty")]
25 pub tags: Vec<String>,
26 /// Keyword shortcut for the bookmark.
27 #[serde(default, skip_serializing_if = "String::is_empty")]
28 pub keyword: String,
29 /// Date added as microseconds since Unix epoch.
30 pub date_added: i64,
31 /// Last modified as microseconds since Unix epoch.
32 pub last_modified: i64,
33 /// Firefox sync GUID.
34 pub guid: String,
35}
36
37/// A separator entry in a bookmark folder.
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct Separator {
40 /// Date added as microseconds since Unix epoch.
41 pub date_added: i64,
42 /// Last modified as microseconds since Unix epoch.
43 pub last_modified: i64,
44 /// Firefox sync GUID.
45 pub guid: String,
46}
47
48/// Index file for explicit ordering of items in a folder.
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct FolderIndex {
51 /// Ordered list of item names.
52 /// - Bookmarks: filename without `.toml` extension
53 /// - Separators: `---{guid}`
54 /// - Subfolders: `name/` (trailing slash)
55 pub order: Vec<String>,
56}
57
58/// Internal representation of a folder from the database.
59#[derive(Debug, Clone)]
60pub struct Folder {
61 /// Database ID.
62 pub id: i64,
63 /// Parent folder ID.
64 pub parent: i64,
65 /// Folder title.
66 pub title: String,
67}
68
69/// Internal representation of a bookmark from the database.
70#[derive(Debug, Clone)]
71pub struct DbBookmark {
72 /// Parent folder ID.
73 pub parent: i64,
74 /// Place ID (foreign key to `moz_places`).
75 pub place_id: Option<i64>,
76 /// Bookmark title.
77 pub title: String,
78 /// Position within parent.
79 pub position: i32,
80 /// Firefox sync GUID.
81 pub guid: String,
82 /// Date added as microseconds since Unix epoch.
83 pub date_added: i64,
84 /// Last modified as microseconds since Unix epoch.
85 pub last_modified: i64,
86}
87
88/// Internal representation of a separator from the database.
89#[derive(Debug, Clone)]
90pub struct DbSeparator {
91 /// Parent folder ID.
92 pub parent: i64,
93 /// Position within parent.
94 pub position: i32,
95 /// Firefox sync GUID.
96 pub guid: String,
97 /// Date added as microseconds since Unix epoch.
98 pub date_added: i64,
99 /// Last modified as microseconds since Unix epoch.
100 pub last_modified: i64,
101}
102
103/// Root folder IDs in Firefox bookmarks.
104pub mod roots {
105 /// The root of all bookmark folders.
106 pub const ROOT: i64 = 1;
107 /// Bookmarks Menu folder.
108 pub const MENU: i64 = 2;
109 /// Bookmarks Toolbar folder.
110 pub const TOOLBAR: i64 = 3;
111 /// Tags folder (internal, not exported).
112 pub const TAGS: i64 = 4;
113 /// Other Bookmarks folder.
114 pub const OTHER: i64 = 5;
115 /// Mobile Bookmarks folder.
116 pub const MOBILE: i64 = 6;
117}
118
119/// Bookmark item types in `moz_bookmarks`.
120pub mod item_types {
121 /// A bookmark (URL).
122 pub const BOOKMARK: i32 = 1;
123 /// A folder.
124 pub const FOLDER: i32 = 2;
125 /// A separator line.
126 pub const SEPARATOR: i32 = 3;
127}
128
129/// Map a root folder ID to its export directory name.
130#[must_use]
131pub fn root_dir_name(root_id: i64) -> Option<&'static str> {
132 match root_id {
133 roots::MENU => Some("menu"),
134 roots::TOOLBAR => Some("toolbar"),
135 roots::OTHER => Some("other"),
136 roots::MOBILE => Some("mobile"),
137 _ => None,
138 }
139}
140
141/// Map a directory name back to a root folder ID.
142#[must_use]
143pub fn dir_name_to_root(name: &str) -> Option<i64> {
144 match name {
145 "menu" => Some(roots::MENU),
146 "toolbar" => Some(roots::TOOLBAR),
147 "other" => Some(roots::OTHER),
148 "mobile" => Some(roots::MOBILE),
149 _ => None,
150 }
151}