librespot/capi/src/metadata.rs

88 lines
2 KiB
Rust
Raw Normal View History

2016-01-26 23:21:57 +00:00
use eventual::Async;
use std::sync::Arc;
use std::ffi::CStr;
use std::cell::UnsafeCell;
2016-01-26 23:21:57 +00:00
use librespot::metadata::{MetadataTrait, MetadataRef};
use cstring_cache::CStringCache;
use session::SpSession;
pub struct UnsafeSyncCell<T> {
cell: UnsafeCell<T>
}
impl <T> UnsafeSyncCell<T> {
fn new(value: T) -> UnsafeSyncCell<T> {
UnsafeSyncCell { cell: UnsafeCell::new(value) }
}
fn get(&self) -> *mut T {
self.cell.get()
}
}
unsafe impl<T> Sync for UnsafeSyncCell<T> {}
pub enum SpMetadataState<T: MetadataTrait> {
2016-01-26 23:21:57 +00:00
Loading,
Error,
Loaded(T),
}
pub struct SpMetadata<T: MetadataTrait> {
state: Arc<UnsafeSyncCell<SpMetadataState<T>>>,
cache: CStringCache,
}
2016-01-26 23:21:57 +00:00
impl <T: MetadataTrait> SpMetadata<T> {
pub fn from_future(future: MetadataRef<T>) -> SpMetadata<T> {
let state = Arc::new(UnsafeSyncCell::new(SpMetadataState::Loading));
2016-01-26 23:21:57 +00:00
{
let state = state.clone();
SpSession::receive(future, move |session, result| {
let state = unsafe {
&mut *state.get()
};
*state = match result {
Ok(data) => SpMetadataState::Loaded(data),
Err(_) => SpMetadataState::Error,
2016-01-26 23:21:57 +00:00
};
unsafe {
if let Some(f) = session.callbacks.metadata_updated {
f(session as *mut _)
}
}
2016-01-26 23:21:57 +00:00
});
}
SpMetadata {
state: state,
cache: CStringCache::new(),
}
2016-01-26 23:21:57 +00:00
}
pub fn is_loaded(&self) -> bool {
unsafe {
self.get().is_some()
}
2016-01-26 23:21:57 +00:00
}
pub unsafe fn get(&self) -> Option<&'static T> {
let state = &*self.state.get();
2016-01-26 23:21:57 +00:00
match *state {
SpMetadataState::Loaded(ref metadata) => Some(metadata),
2016-01-26 23:21:57 +00:00
_ => None,
}
}
pub fn intern(&mut self, string: &str) -> &CStr {
self.cache.intern(string)
}
2016-01-26 23:21:57 +00:00
}