Golang levelDB struct - struct

I'm trying to use following DB API: https://godoc.org/github.com/syndtr/goleveldb/leveldb#
(simple file based key/value DB)
I was able to put and get "key"s into the database.
However, I'm wondering if value can be a struct such as:
type Thm struct {
Name string
Age int
}
Then,
var Tmp Thm
Tmp.Name = "Gon"
Tmp.Age = 33
db.Put([]byte("test3"), []byte(Tmp), nil)
Right now, the error I'm getting is "cannot covert Tmp (type Thm) to type []byte.
If you have experiences with levelDB, could you help me how normally this will be done?
OR, should I convert struct into byte in order to make this work?
Thank you

levelDB only supports strings/byte arrays as keys and values. This is actually a pretty smart feature, because it keeps serialization of complex data structures at the application level. To serialize your Thm struct you can try the gob package if you don't need applications in other languages to be able to read the values, or protobufs, json, or msgpack if you need the serialized data to be accessible to other languages.

Related

Rust tonic and prost_types conversion

I'm using tonic framework, a rust grpc server implementation. In the generated rust code from the proto file, I have a struct which has a field:
#[prost(message, optional, tag="3")]
pub data: ::core::option::Option<::prost_types::Value>,
generated from a protobuff field:
google.protobuf.Value data = 3;
I can't seem to find a way to init data which is type prost_types::Value by converting a struct I have. I'm doing something like:
prost_types::Value::try_from(myOwnsStructVar)
But it does not work. Anyone have used prost_types lib before and know how to encode/convert to prost_types::Value
myOwnsStructVar is a type struct. I need to convert it to prost_types::Struct So then I can do:
prost_types::value::Kind::StructValue(myOwnsStructVarAfterConversiontToProstStruct)
Just from looking at the docs, we can see that Value is a struct with a single public field kind which is of type Option<Kind>. The docs say that if this field is None then that indicates an error. If you look at the docs for Kind, then it's apparent this is where the actual data is stored. So if you want to initialize something of type Value then you'd want to do something like the following, substituting in the appropriate variant of Kind for your use case:
Value {
kind: Some(Kind::NumberValue(10.0f64))
}
The reason that your try_from solution didn't work is because there are no TryFrom implementations for Value other than the default blanket implementation.

How do I convert an struct of type Data to an object of type CNGroup?

I'm having trouble converting a CNGroup object to a Data object and back to a CNGroup object. I decided to start rethinking the problem again. Somewhere along the way I decided that I should use the Data class to save a CNGroup object to CloudKit. I also learned that the field type to use in my CKRecord object would be of the type bytes.
Am I correct so far?
I am able to convert a CNGroup object to a Data object and back again unless I store the Data object in CloudKit and then retrieve it before I convert the Data object back to a CNGroup object, in which case I get an error when I try to access the pointee property of the typed pointer. That would be an UnsafeBufferPointer, an UnsafeMutableBufferPointer, or an UnsafePointer.
I've tried a lot of different code using different ways. It is impractical to put so much code in my post. I have used the copyBytes method and the withUnsafeBytes method of the Data object.
There is one simple code, and that is when I converted the CNGroup object to a Data object:
func convertCNGroupToData(fromCNGroup group: inout CNGroup) -> Data {
return Data(bytes: &group, count: MemoryLayout.size(ofValue: group))
}
I am looking for a simple way to do what I want. I am relooking at Apple's documentation of Data and NSData.
I am not able to be more specific with this question. I appreciate any effort to help me with this.

Ormlite int based enums coming as varchar(max)

Can anyone tell me how to correctly get ORMLite to store enums as integers? I know that this was not supported in 2012 but i found code for some unit tests that suggest it should work now but it doesn't. When we try the column gets created as a varchar(max) in ms sql. We currently use a wrapping property that is ignored to convert the enum value to int but then you can't use it for queries etc so it is less than ideal.
Add a [Flags] attribute to enums you want ServiceStack to treat as integers.
From v4.0.54 you can also use the [EnumAsInt] attribute which will save the enum as an int in OrmLite but still serialize it as a string.

CFBitVector stored as an attribute to a coredata object

I am attempting to create a fingerprint for an object in coreData, and want to set it as attribute to an object. I figured CFBitArray is the way to go.
I am trying to figure out how to save this per object:
Here is an example
Object
attributes:
Name:
Fingerprint ("01010101010101010101010110") etc...
This is used to try to match with a master print
Any suggestions?
You'd have to convert that to/from something Core Data understands, and save the converted value. There are a couple of possibilities, both of which involve getting the actual bits via CFBitVectorGetBits. Once you have that, you can
Save them in an NSData using something like +dataWithBytes:length:, and put that in a binary-type attribute on a managed object. Or...
Depending on the number of bytes you're using, save them in an NSNumber using something like +numberWithLong: (or whatever is long enough for the number of bits). Then put that in one of Core Data's integer types-- again, choosing whatever size fits your bits.
You can make the conversion either by using custom accessor methods on your NSManagedObject subclass, or by using the transformable Core Data attribute type and a value transformer class. For the latter you'd subclass NSValueTransformer and implement your conversions there (Apple provides a couple of examples of this).
Depending on what you're actually doing, you might want to consider using NSIndexSet instead of CFBitVectorRef. If nothing else, it conforms to NSCoding-- which means you can use a transformable attribute but rely on Core Data's default value transformer instead of writing your own.
You might also find it a lot simpler to just use one of the integer types and rely on bitwise operators to determine if a bit is set. Then you don't need to do anything special with Core Data, you just choose the appropriately-sized integer type.
Why are you not just storing NSData? It is way, way easier to store binary data inside NSData than inside CFBitvectorRef.
If you're trying to store a hash / fingerprint of something, I assume you're creating a SHA-256 hash with CC_SHA256_Init, _Update and _Final. Those will give you a so-called digest which is a fingerprint of the data you pass into the CC_SHA256_Update.
// Create the context:
CC_SHA256_CTX shaContext;
CC_SHA256_Init(&shaContext);
// For each value:
CC_SHA256_Update(&shaContext, &v, sizeof(v));
// Get the fingerprint / digest:
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256_Final(digest, &shaContext);
NSData *fingerprint = [NSData dataWithBytes:digest length:sizeof(digest)];
Then you can store that fingerprint into a Core Data attribute that's Binary Data.
Depending on the type of v, you might have to change the call to CC_SHA256_Update(). If you do this on an NSObject, you need to call it for each instance variable that you're interested in (that should be part of the fingerprint), e.g. if you have
#property (nonatomic) int32_t count;
#property (nonatomic, copy) NSString *name;
you'd do
int32_t v = self.count
CC_SHA256_Update(&shaContext, &v, sizeof(v));
NSData *d = [self.name dataUsingEncoding:NSUTF8Stringencoding];
CC_SHA256_Update(&shaContext, [data bytes], [data length]);

Storing object in Esent persistent dictionary gives: Not supported for SetColumn Parameter error

I am trying to save an Object which implements an Interface say IInterface.
private PersistentDictionary<string, IInterface> Object = new PersistentDictionary<string, IInterface>(Environment.CurrentDirectory + #"\Object");
Since many classes implement the same interface(all of which need to cached), for a generic approach I want to store an Object of type IInterface in the dictionary.
So that anywhere I can pull out that object type cast it as IInterface and use that object's internal implementation of methods etc..
But, as soon as the Esent cache is initialized it throws this error:
Not supported for SetColumn
Parameter name: TColumn
Actual value was IInterface.
I have tried to not use XmlSerializer to do the same but is unable to deserialize an Interface type.Also, [Serializable] attribute cannot be used on top of a Interface, so I am stuck.
I have also tried to make all the implementations(classes) of the Interface as [Serializable] as a dying attempt but to no use.
Does any one know a way out ? Thanks in advance !!!
The only reason that only structs are supported (as well as some basic immutable classes such as string) is that the PersistentDictionary is meant to be a drop-in replacement for Dictionary, SortedDictionary and other similar classes.
Suppose I have the following code:
class MyClass
{
int val;
}
.
.
.
var dict = new Dictionary<int,MyClass>();
var x = new MyClass();
x.val = 1;
dict.Add(0,x);
x.val = 2;
var y = dict[0];
Console.WriteLine(y.val);
The output in this case would be 2. But if I'd used the PersistentDictionary instead of the regular one, the output would be 1. The class was created with value 1, and then changed after it was added to the dictionary. Since a class is a reference type, when we retrieve the item from the dictionary, we will also have the changed data.
Since the PersistentDictionary writes the data to disk, it cannot really handle reference types this way. Serializing it, and writing it to disk is essentially the same as treating the object as a value type (an entire copy is made).
Because it's intended to be used instead of the standard dictionaries, and the fact that it cannot handle reference types with complete transparency, the developers instead opted to support only structs, because structs are value types already.
However, if you're aware of this limitation and promise to be careful not to fall into this trap, you can allow it to serialize classes quite easily. Just download the source code and compile your own version of the EsentCollections library. The only change you need to make to it is to change this line:
if (!(type.IsValueType && type.IsSerializable))
to this:
if (!type.IsSerializable)
This will allow classes to be written to the PersistentDictionary as well, provided that it's Serializable, and its members are Serializable as well. A huge benefit is that it will also allow you to store arrays in there this way. All you have to keep in mind is that it's not a real dictionary, therefore when you write an object to it, it will store a copy of the object. Therefore, updating any of your object's members after adding them to the PersistentDictionary will not update the copy in the dictionary automatically as well, you'd need to remember to update it manually.
PersistentDictionary can only store value-structs and a very limited subset of classes (string, Uri, IPAddress). Take a look at ColumnConverter.cs, at private static bool IsSerializable(Type type) for the full restrictions. You'd be hitting the typeinfo.IsValueType() restriction.
By the way, you can also try posting questions about PersistentDictionary at http://managedesent.codeplex.com/discussions .
-martin

Resources