musikr: improve xiph fieldlistmap lifecycle mgmt

This commit is contained in:
Alexander Capehart 2025-02-17 08:42:54 -07:00
parent 024cadf530
commit fa87ea09b8
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
2 changed files with 9 additions and 10 deletions

View file

@ -138,8 +138,10 @@ mod bridge_impl {
#[namespace = "TagLib::Ogg"] #[namespace = "TagLib::Ogg"]
#[cxx_name = "XiphComment"] #[cxx_name = "XiphComment"]
type CPPXiphComment; type CPPXiphComment;
// Explicit lifecycle definition to state while the Pin is temporary, the CPPFieldListMap
// ref returned actually has the same lifetime as the CPPXiphComment.
#[cxx_name = "fieldListMap"] #[cxx_name = "fieldListMap"]
fn fieldListMap(self: Pin<&CPPXiphComment>) -> &CPPFieldListMap; fn fieldListMap<'slf, 'file_ref>(self: Pin<&'slf CPPXiphComment>) -> &'file_ref CPPFieldListMap;
#[namespace = "TagLib"] #[namespace = "TagLib"]
#[cxx_name = "SimplePropertyMap"] #[cxx_name = "SimplePropertyMap"]

View file

@ -16,12 +16,9 @@ impl<'file_ref> XiphComment<'file_ref> {
} }
pub fn field_list_map<'slf>(&'slf self) -> FieldListMap<'file_ref> { pub fn field_list_map<'slf>(&'slf self) -> FieldListMap<'file_ref> {
let map: &'slf CPPFieldListMap = self.this.pin().fieldListMap(); let map: &'file_ref CPPFieldListMap = self.this.pin().fieldListMap();
// CPPFieldListMap exists for as long as the XiphComment, so we can transmute it let map_this = unsafe { RefThis::new(map) };
// to the file_ref lifetime. FieldListMap::new(map_this)
let extended_map: &'file_ref CPPFieldListMap = unsafe { std::mem::transmute(map) };
let map_pin = unsafe { Pin::new_unchecked(extended_map) };
FieldListMap::new(map_pin)
} }
pub fn picture_list(&mut self) -> Option<PictureList<'file_ref>> { pub fn picture_list(&mut self) -> Option<PictureList<'file_ref>> {
@ -32,18 +29,18 @@ impl<'file_ref> XiphComment<'file_ref> {
} }
pub struct FieldListMap<'file_ref> { pub struct FieldListMap<'file_ref> {
this: Pin<&'file_ref CPPFieldListMap>, this: RefThis<'file_ref, CPPFieldListMap>,
} }
impl<'file_ref> FieldListMap<'file_ref> { impl<'file_ref> FieldListMap<'file_ref> {
pub fn new(this: Pin<&'file_ref CPPFieldListMap>) -> Self { pub fn new(this: RefThis<'file_ref, CPPFieldListMap>) -> Self {
Self { this } Self { this }
} }
} }
impl<'file_ref> FieldListMap<'file_ref> { impl<'file_ref> FieldListMap<'file_ref> {
pub fn to_hashmap(&self) -> HashMap<String, Vec<String>> { pub fn to_hashmap(&self) -> HashMap<String, Vec<String>> {
let cxx_vec = FieldListMap_to_entries(self.this); let cxx_vec = FieldListMap_to_entries(self.this.pin());
cxx_vec cxx_vec
.iter() .iter()
.map(|property| { .map(|property| {