Skip to main content

ModelStore

Trait ModelStore 

Source
pub trait ModelStore {
Show 40 methods // Required methods fn read(&self, name: &str) -> Option<String>; fn write(&self, name: &str, contents: &str) -> Result<(), String>; fn mutation_generation(&self) -> u64; // Provided methods fn backend_label(&self) -> String { ... } fn list(&self) -> Vec<String> { ... } fn remove(&self, _name: &str) -> Result<(), String> { ... } fn residency(&self, name: &str) -> Residency { ... } fn identity(&self, identity: &str) -> DocumentIdentity { ... } fn display_name(&self, identity: &str) -> String { ... } fn sibling_of(&self, identity: &str, file_name: &str) -> Option<String> { ... } fn canonical_identity(&self, name: &str) -> String { ... } fn take_persistence_errors(&self) -> Vec<String> { ... } fn plm_session(&self) -> Option<Session> { ... } fn plm_client(&self) -> Option<Rc<PlmClient>> { ... } fn plm_revision(&self, key: &str) -> Option<IndexEntry> { ... } fn refresh_plm_index(&self, keys: &[String], stale: bool) { ... } fn remember_saved_document(&self, name: &str, contents: &str) { ... } fn local_files(&self) -> Option<&dyn ModelStore> { ... } fn begin_pick_file(&self) -> Result<(), String> { ... } fn take_picked_file(&self) -> Option<ImportedFile> { ... } fn pending_writes(&self) -> usize { ... } fn browser_location(&self) -> String { ... } fn browser_entries(&self, _extensions: &[&str]) -> Vec<BrowserEntry> { ... } fn browser_enter(&self, _identity: &str) -> Result<(), String> { ... } fn browser_up(&self) -> Result<(), String> { ... } fn browser_home(&self) -> Result<(), String> { ... } fn browser_root(&self) -> Result<(), String> { ... } fn browser_navigate(&self, _location: &str) -> Result<(), String> { ... } fn browser_places(&self) -> Vec<BrowserPlace> { ... } fn browser_create_dir(&self, _name: &str) -> Result<(), String> { ... } fn browser_write( &self, name: &str, contents: &str, ) -> Result<String, String> { ... } fn list_external_files(&self, _extensions: &[&str]) -> Vec<String> { ... } fn read_external_file(&self, _name: &str) -> Option<Vec<u8>> { ... } fn supports_file_interchange(&self) -> bool { ... } fn export_file( &self, name: &str, contents: &str, ) -> Result<Option<String>, String> { ... } fn begin_import(&self) -> Result<(), String> { ... } fn take_import(&self) -> Option<ImportedFile> { ... } fn begin_import_filtered( &self, _filter: (&str, &[&str]), ) -> Result<(), String> { ... } fn export_file_named( &self, _file_name: &str, _contents: &str, ) -> Result<(), String> { ... } fn export_file_named_bytes( &self, _file_name: &str, _contents: &[u8], ) -> Result<(), String> { ... }
}
Expand description

The application’s single persistent-storage abstraction. Reserved application keys and named model documents are read and written through the same methods. All methods take &self; mutable backend state lives behind interior mutability.

Required Methods§

Source

fn read(&self, name: &str) -> Option<String>

Read a stored document by name, or None if absent/unreadable.

Source

fn write(&self, name: &str, contents: &str) -> Result<(), String>

Create or overwrite the document name with contents. Err carries a message the panel surfaces in its status line.

Source

fn mutation_generation(&self) -> u64

A monotonic count of this store’s MUTATIONS — every write, remove and browser_write that landed, WHOEVER made it. A read never moves it; two reads that agree mean nothing was written in between.

This is a cache-invalidation key, which is why it is REQUIRED rather than defaulted: a default would let a new backend (the GitHub one this trait is shaped for) compile while silently never invalidating anything, which is the failure it exists to stop. The outdated-parts badge (panels::update_components) used to key on the file dialog’s own save counter, which counts Save / Save As / native Save-As and NOTHING else — so a KiCad re-import (panels::kicad_bulk::write_part) or the explorer’s delete row could change a part’s source under an open assembly, move no other generation, and leave the badge dark.

Provided Methods§

Source

fn backend_label(&self) -> String

A short human label of where documents persist, for the panel header (e.g. "filesystem: ~/.config/brep-app/models" or "browser storage").

Source

fn list(&self) -> Vec<String>

The names of the documents currently available to Open (bare names, no extension). May be empty on a backend that cannot enumerate — then the panel falls back to the name field / import.

Source

fn remove(&self, _name: &str) -> Result<(), String>

Delete the document name (best-effort; Ok if it is already gone).

Source

fn residency(&self, name: &str) -> Residency

Whether name is absent, listed but not yet loaded, or readable now (see Residency). The default answers from read, which is exact for every store that holds what it lists; only an index-hydrated store overrides it. No caller branches on OnDisk yet — it is here so one CAN tell “not loaded yet” from “gone” without a second store API.

Source

fn identity(&self, identity: &str) -> DocumentIdentity

What kind of identity identity is on THIS store (see DocumentIdentity and the enumeration above it). Every file backend keys by path, so the default never parses: a browser folder named part/7/rev holds a document, not a revision.

Source

fn display_name(&self, identity: &str) -> String

The name a person sees for identity: the tab title, the name field. The default is the file rule, [model_display_name]; a PLM store knows the part number and revision label from its index, which the key alone does not carry.

Source

fn sibling_of(&self, identity: &str, file_name: &str) -> Option<String>

The identity of file_name beside the document identity — or None on a store with no folders to be beside (the PLM, where a family member or a spun-out part is a new part instead, S7 / S9). The default is the file rule, sibling_identity.

Source

fn canonical_identity(&self, name: &str) -> String

The ONE spelling of the document name resolves to, as the explorer spells it (BrowserEntry::identity), so two names for one document compare equal: a bare bolt and /home/u/.config/brep-app/models/bolt.nbrep on the desktop, sub/bolt and /models/sub/bolt.nbrep in the browser.

The adoption importer (S13) needs it. An assembly’s sourceKeys are whatever name the part was inserted by, and the importer must match each one to the file it walked. The default is name unchanged, which is right for a store with one spelling per document (a PLM store’s revision keys).

Source

fn take_persistence_errors(&self) -> Vec<String>

Persistence failures that surfaced AFTER a write / remove already returned Ok — the price of a WRITE-BEHIND backend (see [mirror_store]). The app shell drains this once per frame into the toast overlay, so a save that never reached storage is never silent: the in-memory copy means nothing is lost mid-session, but the user has to know it will not survive a reload. Empty on a backend that writes synchronously (native files), which reports through write’s Err instead.

Source

fn plm_session(&self) -> Option<Session>

The PLM this session is on, or is configured for and not on (why, when known): what the Settings PLM tab shows (plan S1 part 3). None is the file-based app, and the tab is absent.

Source

fn plm_client(&self) -> Option<Rc<PlmClient>>

The signed-in PLM client of a session whose store IS the PLM, for the calls that are not store reads and writes (Generate, spin-out, the lifecycle verbs). None on every file store, and on a PLM configured but not connected.

Source

fn plm_revision(&self, key: &str) -> Option<IndexEntry>

What the PLM’s store index says of revision key (part/…/rev/…): its part number, label, lifecycle and lock, as the session last read them. None on every file store and for a key the index does not list. No request: this is the index the session already holds.

Source

fn refresh_plm_index(&self, keys: &[String], stale: bool)

Bring the held index up to date after the change feed moved: keys are the revisions the feed named, stale means it could not say. A no-op on every file store.

Source

fn remember_saved_document(&self, name: &str, contents: &str)

Remember a document that has already been durably written through a PLM request. Update the session mirror without issuing a second write.

Source

fn local_files(&self) -> Option<&dyn ModelStore>

This machine’s own files, browsable, for the file chooser (any file, any folder): the native file store itself, or the file store a PLM session keeps beside the server. None in the browser, which picks through Self::begin_pick_file instead.

Source

fn begin_pick_file(&self) -> Result<(), String>

The browser’s file chooser for ANY file (not the model lane’s .nbrep input): the choice arrives later through Self::take_picked_file, under the file’s own name.

Source

fn take_picked_file(&self) -> Option<ImportedFile>

The file Self::begin_pick_file’s chooser delivered, once.

Source

fn pending_writes(&self) -> usize

Writes handed to a WRITE-BEHIND backend that have not settled yet — the status bar’s working indicator reports them (“Saving to browser storage”). Always 0 on a backend that writes synchronously.

Source

fn browser_location(&self) -> String

Current directory shown by the embedded explorer.

Source

fn browser_entries(&self, _extensions: &[&str]) -> Vec<BrowserEntry>

Directories and matching files at the current explorer location. Directories are never filtered. The default implementation presents the backend’s named model collection as a flat virtual directory.

Source

fn browser_enter(&self, _identity: &str) -> Result<(), String>

Source

fn browser_up(&self) -> Result<(), String>

Source

fn browser_home(&self) -> Result<(), String>

Source

fn browser_root(&self) -> Result<(), String>

Source

fn browser_navigate(&self, _location: &str) -> Result<(), String>

Navigate the explorer directly to location — a value previously returned by Self::browser_location, a BrowserPlace::location, a breadcrumb ancestor, or a user-typed path. Err if it is not a directory this backend can browse. Powers the breadcrumb, the sidebar, back/forward, and the path-edit field. Default: unsupported.

Source

fn browser_places(&self) -> Vec<BrowserPlace>

Quick-access places for the explorer’s left sidebar (home, documents, the models root, disks…). Default: none, and the sidebar hides itself.

Source

fn browser_create_dir(&self, _name: &str) -> Result<(), String>

Create a child directory at the current browser location.

Source

fn browser_write(&self, name: &str, contents: &str) -> Result<String, String>

Write a filename at the current browser location and return its stable identity for subsequent plain Save operations.

Source

fn list_external_files(&self, _extensions: &[&str]) -> Vec<String>

Files available to the in-app explorer for a foreign-format import. Names retain their extension. Browser storage returns none and offers an Upload button instead; desktop enumerates its application files directory.

Source

fn read_external_file(&self, _name: &str) -> Option<Vec<u8>>

Read one entry returned by Self::list_external_files.

Source

fn supports_file_interchange(&self) -> bool

Whether this backend can exchange files with the user’s real filesystem (browser download+upload). The panel shows the Upload affordance only when this is true.

Source

fn export_file( &self, name: &str, contents: &str, ) -> Result<Option<String>, String>

Hand contents to the user as a file named after name (browser: a download; native w/ dialog: a Save-As). Returns the saved document’s identity — the full path the user chose on native (so the caller can re-save straight to it), the bare download name on the web — or None when the user cancelled. No-op (None) by default.

Source

fn begin_import(&self) -> Result<(), String>

Begin importing a real file — opens the platform picker. The result is retrieved later via Self::take_import (upload/read is async in the browser). No-op by default.

Source

fn take_import(&self) -> Option<ImportedFile>

Poll for a completed import, consuming it. None until a begin_import finishes. Default: never any.

Source

fn begin_import_filtered(&self, _filter: (&str, &[&str])) -> Result<(), String>

Begin importing a real file behind a specific picker filter (a human label + dot-less extensions, e.g. ("STEP", &["step","stp"])). The chosen file’s contents + its FULL name (extension preserved, so the panel can route it) arrive via Self::take_import. Default: reuse Self::begin_import.

Source

fn export_file_named( &self, _file_name: &str, _contents: &str, ) -> Result<(), String>

Hand contents to the user under EXACTLY file_name (extension included, no model-extension munging) — the Save-As / download for a foreign export format. The file’s media type comes from its extension (media_type). Default no-op (interchange unsupported).

Source

fn export_file_named_bytes( &self, _file_name: &str, _contents: &[u8], ) -> Result<(), String>

Self::export_file_named for a BINARY format (GLB, a sheet PDF). Every text export could go through this one — text is bytes — but the text method stays because the browser’s Blob takes a string directly and routing UTF-8 through a Uint8Array for every STEP file would be a copy for nothing. Both lanes type the file the same way, from its extension, so which lane an export takes is a question about copies and never about what the user receives. Default no-op, like its text sibling.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§