зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1530506 - Add a generic writable property bag wrapper for Rust code. r=nika
This commit adds a `storage_variant::HashPropertyBag` type that exposes an idiomatic Rust interface for `nsIWritablePropertyBag`. Differential Revision: https://phabricator.services.mozilla.com/D21062 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
41138306e0
Коммит
8f82f61df9
|
@ -0,0 +1,94 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use nserror::{nsresult, NS_OK};
|
||||
use nsstring::nsString;
|
||||
use xpcom::{getter_addrefs, interfaces::nsIWritablePropertyBag, RefPtr};
|
||||
|
||||
use crate::VariantType;
|
||||
|
||||
extern "C" {
|
||||
fn NS_NewHashPropertyBag(bag: *mut *const nsIWritablePropertyBag) -> libc::c_void;
|
||||
}
|
||||
|
||||
/// A hash property bag backed by storage variant values.
|
||||
pub struct HashPropertyBag(RefPtr<nsIWritablePropertyBag>);
|
||||
|
||||
impl Default for HashPropertyBag {
|
||||
fn default() -> HashPropertyBag {
|
||||
// This is safe to unwrap because `NS_NewHashPropertyBag` is infallible.
|
||||
let bag = getter_addrefs(|p| {
|
||||
unsafe { NS_NewHashPropertyBag(p) };
|
||||
NS_OK
|
||||
}).unwrap();
|
||||
HashPropertyBag(bag)
|
||||
}
|
||||
}
|
||||
|
||||
impl HashPropertyBag {
|
||||
/// Creates an empty property bag.
|
||||
#[inline]
|
||||
pub fn new() -> HashPropertyBag {
|
||||
HashPropertyBag::default()
|
||||
}
|
||||
|
||||
/// Returns the value for a property name. Fails with `NS_ERROR_FAILURE`
|
||||
/// if the property doesn't exist, or `NS_ERROR_CANNOT_CONVERT_DATA` if the
|
||||
/// property exists, but is not of the value type `V`.
|
||||
pub fn get<K, V>(&self, name: K) -> Result<V, nsresult>
|
||||
where
|
||||
K: AsRef<str>,
|
||||
V: VariantType,
|
||||
{
|
||||
getter_addrefs(|p| unsafe { self.0.GetProperty(&*nsString::from(name.as_ref()), p) })
|
||||
.and_then(|v| V::from_variant(v.coerce()))
|
||||
}
|
||||
|
||||
/// Returns the value for a property name, or the default if not set or
|
||||
/// not of the value type `V`.
|
||||
#[inline]
|
||||
pub fn get_or_default<K, V>(&self, name: K) -> V
|
||||
where
|
||||
K: AsRef<str>,
|
||||
V: VariantType + Default,
|
||||
{
|
||||
self.get(name).unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Sets a property with the name to the value, overwriting any previous
|
||||
/// value.
|
||||
pub fn set<K, V>(&mut self, name: K, value: V)
|
||||
where
|
||||
K: AsRef<str>,
|
||||
V: VariantType,
|
||||
{
|
||||
let v = value.into_variant();
|
||||
unsafe {
|
||||
// This is safe to unwrap because
|
||||
// `nsHashPropertyBagBase::SetProperty` only returns an error if `v`
|
||||
// is a null pointer.
|
||||
self.0
|
||||
.SetProperty(&*nsString::from(name.as_ref()), v.coerce())
|
||||
.to_result()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// Deletes a property with the name. Returns `true` if the property
|
||||
/// was previously in the bag, `false` if not.
|
||||
pub fn delete(&mut self, name: impl AsRef<str>) -> bool {
|
||||
unsafe {
|
||||
self.0
|
||||
.DeleteProperty(&*nsString::from(name.as_ref()))
|
||||
.to_result()
|
||||
.is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the backing `nsIWritablePropertyBag`.
|
||||
#[inline]
|
||||
pub fn bag(&self) -> &nsIWritablePropertyBag {
|
||||
&self.0
|
||||
}
|
||||
}
|
|
@ -7,11 +7,15 @@ extern crate nserror;
|
|||
extern crate nsstring;
|
||||
extern crate xpcom;
|
||||
|
||||
mod bag;
|
||||
|
||||
use libc::{c_double, int64_t, uint16_t};
|
||||
use nserror::{nsresult, NS_OK};
|
||||
use nsstring::{nsACString, nsAString, nsCString, nsString};
|
||||
use xpcom::{getter_addrefs, interfaces::nsIVariant, RefPtr};
|
||||
|
||||
pub use crate::bag::HashPropertyBag;
|
||||
|
||||
extern "C" {
|
||||
fn NS_GetDataType(variant: *const nsIVariant) -> uint16_t;
|
||||
fn NS_NewStorageNullVariant(result: *mut *const nsIVariant);
|
||||
|
|
|
@ -14,6 +14,16 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
// This function uses C linkage because it's exposed to Rust to support the
|
||||
// `HashPropertyBag` wrapper in the `storage_variant` crate.
|
||||
void NS_NewHashPropertyBag(nsIWritablePropertyBag** aBag) {
|
||||
MakeRefPtr<nsHashPropertyBag>().forget(aBag);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/*
|
||||
* nsHashPropertyBagBase implementation.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче