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}