@@ -1558,40 +1558,54 @@ impl<T: ThreadMode> DBWithThreadMode<T> {
15581558 Ok ( ( ) )
15591559 }
15601560
1561- /// Retrieves a RocksDB property by name .
1561+ /// Implementation for property_value et al methods .
15621562 ///
1563- /// Full list of properties could be find
1564- /// [here](https://github.com/facebook/rocksdb/blob/08809f5e6cd9cc4bc3958dd4d59457ae78c76660/include/rocksdb/db.h#L428-L634).
1565- pub fn property_value ( & self , name : & str ) -> Result < Option < String > , Error > {
1566- let prop_name = match CString :: new ( name) {
1567- Ok ( c) => c,
1563+ /// `name` is the name of the property. It will be converted into a CString
1564+ /// and passed to `get_property` as argument. `get_property` reads the
1565+ /// specified property and either returns NULL or a pointer to a C allocated
1566+ /// string; this method takes ownership of that string and will free it at
1567+ /// the end. That string is parsed using `parse` callback which produces
1568+ /// the returned result.
1569+ fn property_value_impl < R > (
1570+ name : & str ,
1571+ get_property : impl FnOnce ( * const c_char ) -> * mut c_char ,
1572+ parse : impl FnOnce ( & str ) -> Result < R , Error > ,
1573+ ) -> Result < Option < R > , Error > {
1574+ let value = match CString :: new ( name) {
1575+ Ok ( prop_name) => get_property ( prop_name. as_ptr ( ) ) ,
15681576 Err ( e) => {
15691577 return Err ( Error :: new ( format ! (
15701578 "Failed to convert property name to CString: {}" ,
15711579 e
15721580 ) ) ) ;
15731581 }
15741582 } ;
1575-
1583+ if value. is_null ( ) {
1584+ return Ok ( None ) ;
1585+ }
1586+ let result = match unsafe { CStr :: from_ptr ( value) } . to_str ( ) {
1587+ Ok ( s) => parse ( s) . map ( |value| Some ( value) ) ,
1588+ Err ( e) => Err ( Error :: new ( format ! (
1589+ "Failed to convert property value to string: {}" ,
1590+ e
1591+ ) ) ) ,
1592+ } ;
15761593 unsafe {
1577- let value = ffi:: rocksdb_property_value ( self . inner , prop_name. as_ptr ( ) ) ;
1578- if value. is_null ( ) {
1579- return Ok ( None ) ;
1580- }
1581-
1582- let str_value = match CStr :: from_ptr ( value) . to_str ( ) {
1583- Ok ( s) => s. to_owned ( ) ,
1584- Err ( e) => {
1585- return Err ( Error :: new ( format ! (
1586- "Failed to convert property value to string: {}" ,
1587- e
1588- ) ) ) ;
1589- }
1590- } ;
1591-
15921594 libc:: free ( value as * mut c_void ) ;
1593- Ok ( Some ( str_value) )
15941595 }
1596+ result
1597+ }
1598+
1599+ /// Retrieves a RocksDB property by name.
1600+ ///
1601+ /// Full list of properties could be find
1602+ /// [here](https://github.com/facebook/rocksdb/blob/08809f5e6cd9cc4bc3958dd4d59457ae78c76660/include/rocksdb/db.h#L428-L634).
1603+ pub fn property_value ( & self , name : & str ) -> Result < Option < String > , Error > {
1604+ Self :: property_value_impl (
1605+ name,
1606+ |prop_name| unsafe { ffi:: rocksdb_property_value ( self . inner , prop_name) } ,
1607+ |str_value| Ok ( str_value. to_owned ( ) ) ,
1608+ )
15951609 }
15961610
15971611 /// Retrieves a RocksDB property by name, for a specific column family.
@@ -1603,53 +1617,34 @@ impl<T: ThreadMode> DBWithThreadMode<T> {
16031617 cf : & impl AsColumnFamilyRef ,
16041618 name : & str ,
16051619 ) -> Result < Option < String > , Error > {
1606- let prop_name = match CString :: new ( name) {
1607- Ok ( c) => c,
1608- Err ( e) => {
1609- return Err ( Error :: new ( format ! (
1610- "Failed to convert property name to CString: {}" ,
1611- e
1612- ) ) ) ;
1613- }
1614- } ;
1615-
1616- unsafe {
1617- let value = ffi:: rocksdb_property_value_cf ( self . inner , cf. inner ( ) , prop_name. as_ptr ( ) ) ;
1618- if value. is_null ( ) {
1619- return Ok ( None ) ;
1620- }
1621-
1622- let str_value = match CStr :: from_ptr ( value) . to_str ( ) {
1623- Ok ( s) => s. to_owned ( ) ,
1624- Err ( e) => {
1625- return Err ( Error :: new ( format ! (
1626- "Failed to convert property value to string: {}" ,
1627- e
1628- ) ) ) ;
1629- }
1630- } ;
1620+ Self :: property_value_impl (
1621+ name,
1622+ |prop_name| unsafe {
1623+ ffi:: rocksdb_property_value_cf ( self . inner , cf. inner ( ) , prop_name)
1624+ } ,
1625+ |str_value| Ok ( str_value. to_owned ( ) ) ,
1626+ )
1627+ }
16311628
1632- libc:: free ( value as * mut c_void ) ;
1633- Ok ( Some ( str_value) )
1634- }
1629+ fn parse_property_int_value ( value : & str ) -> Result < u64 , Error > {
1630+ value. parse :: < u64 > ( ) . map_err ( |err| {
1631+ Error :: new ( format ! (
1632+ "Failed to convert property value {} to int: {}" ,
1633+ value, err
1634+ ) )
1635+ } )
16351636 }
16361637
16371638 /// Retrieves a RocksDB property and casts it to an integer.
16381639 ///
16391640 /// Full list of properties that return int values could be find
16401641 /// [here](https://github.com/facebook/rocksdb/blob/08809f5e6cd9cc4bc3958dd4d59457ae78c76660/include/rocksdb/db.h#L654-L689).
16411642 pub fn property_int_value ( & self , name : & str ) -> Result < Option < u64 > , Error > {
1642- match self . property_value ( name) {
1643- Ok ( Some ( value) ) => match value. parse :: < u64 > ( ) {
1644- Ok ( int_value) => Ok ( Some ( int_value) ) ,
1645- Err ( e) => Err ( Error :: new ( format ! (
1646- "Failed to convert property value to int: {}" ,
1647- e
1648- ) ) ) ,
1649- } ,
1650- Ok ( None ) => Ok ( None ) ,
1651- Err ( e) => Err ( e) ,
1652- }
1643+ Self :: property_value_impl (
1644+ name,
1645+ |prop_name| unsafe { ffi:: rocksdb_property_value ( self . inner , prop_name) } ,
1646+ Self :: parse_property_int_value,
1647+ )
16531648 }
16541649
16551650 /// Retrieves a RocksDB property for a specific column family and casts it to an integer.
@@ -1661,17 +1656,13 @@ impl<T: ThreadMode> DBWithThreadMode<T> {
16611656 cf : & impl AsColumnFamilyRef ,
16621657 name : & str ,
16631658 ) -> Result < Option < u64 > , Error > {
1664- match self . property_value_cf ( cf, name) {
1665- Ok ( Some ( value) ) => match value. parse :: < u64 > ( ) {
1666- Ok ( int_value) => Ok ( Some ( int_value) ) ,
1667- Err ( e) => Err ( Error :: new ( format ! (
1668- "Failed to convert property value to int: {}" ,
1669- e
1670- ) ) ) ,
1659+ Self :: property_value_impl (
1660+ name,
1661+ |prop_name| unsafe {
1662+ ffi:: rocksdb_property_value_cf ( self . inner , cf. inner ( ) , prop_name)
16711663 } ,
1672- Ok ( None ) => Ok ( None ) ,
1673- Err ( e) => Err ( e) ,
1674- }
1664+ Self :: parse_property_int_value,
1665+ )
16751666 }
16761667
16771668 /// The sequence number of the most recent transaction.
0 commit comments