public unsafe DeserializeResult Deserialize(byte[] mass) { Table[] tables; uint userID; DateTime synchDT; int SPos = Encoding.GetByteCount(Mark); { fixed(void *numPtr = &mass[mass.Length - 4]) { userID = *(uint *)numPtr; } fixed(void *numPtr = &mass[mass.Length - 8 - 4]) { synchDT = new DateTime(*(long *)numPtr); } } { int TableCount; fixed(void *numPtr = &mass[SPos]) { TableCount = *(int *)numPtr; } //количество таблиц SPos += 4; tables = new Table[TableCount]; } //гружу записи for (int i = 0; i < tables.Length; i++) { DataBase.ISTable Table; DataBase.ITable Tbl; { string TableName; int TableNameLength; fixed(void *numPtr = &mass[SPos]) { TableNameLength = *(int *)numPtr; } //длина имени таблицы SPos += sizeof(int); TableName = Encoding.GetString(mass, SPos, TableNameLength); //имя таблицы SPos += TableNameLength; Tbl = _dataBase.Tables[TableName]; if (Tbl == null) { throw new Exception($"Таблица не найдена: \"{TableName}\""); } Table = Tbl.CreateSubTable(false); } int RowCount; fixed(void *numPtr = &mass[SPos]) { RowCount = *(int *)numPtr; } SPos += sizeof(int); int RowsDataLength, CheckRowsDataLength = 0; fixed(void *numPtr = &mass[SPos]) { RowsDataLength = *(int *)numPtr; } //длина данных SPos += sizeof(int); var rows = new Row[RowCount]; for (int j = 0; j < RowCount; j++) { CheckRowsDataLength += sizeof(uint) + sizeof(int) + sizeof(DataBase.State); //id+метка об удалении + длина записи int RowDataLength, CheckRowDataLength = sizeof(uint) + sizeof(DataBase.State); //id+метка об удалении fixed(void *numPtr = &mass[SPos]) { RowDataLength = *(int *)numPtr; } //длина следующей записи SPos += sizeof(int); uint ID; fixed(void *numPtr = &mass[SPos]) { ID = *(uint *)numPtr; } //идентификатор SPos += sizeof(uint); DataBase.State InUse; fixed(void *numPtr = &mass[SPos]) { InUse = *(DataBase.State *)numPtr; } //метка об удалении SPos += sizeof(DataBase.State); object[] Values; int ColumnIndex = 0; Values = new object[Tbl.Columns.Count]; //Values[Values.Length - 1] = SPoolID; rows[j] = new Row(ID, InUse, Values); //тут важно, чтобы у всех таблиц были колонки relation spool и располагались в конце for (int k = 0; k < Tbl.Columns.Count - 1; k++) { var column = Tbl.GetColumn(k); if (!column.Protect) { switch (column.TypeCol) { case DataBase.Types.Bool: fixed(void *numPtr = &mass[SPos]) { Values[k] = *(bool *)numPtr; } SPos += sizeof(bool); CheckRowDataLength += sizeof(bool); CheckRowsDataLength += sizeof(bool); break; case DataBase.Types.AutoStatus: fixed(void *numPtr = &mass[SPos]) { Values[k] = (*(bool *)numPtr ? DataBase.AutoStatus.Used : DataBase.AutoStatus.UnUse); } SPos += sizeof(bool); CheckRowDataLength += sizeof(bool); CheckRowsDataLength += sizeof(bool); break; case DataBase.Types.Byte: Values[k] = mass[SPos]; SPos += sizeof(byte); CheckRowDataLength += sizeof(byte); CheckRowsDataLength += sizeof(byte); break; case DataBase.Types.DateTime: fixed(void *numPtr = &mass[SPos]) { Values[k] = new DateTime(*(long *)numPtr); } SPos += sizeof(long); CheckRowDataLength += sizeof(long); CheckRowsDataLength += sizeof(long); break; case DataBase.Types.Double: fixed(void *numPtr = &mass[SPos]) { Values[k] = *(double *)numPtr; } SPos += sizeof(double); CheckRowDataLength += sizeof(double); CheckRowsDataLength += sizeof(double); break; case DataBase.Types.Decimal: fixed(void *numPtr = &mass[SPos]) { Values[k] = *(decimal *)numPtr; } SPos += sizeof(decimal); CheckRowDataLength += sizeof(decimal); CheckRowsDataLength += sizeof(decimal); break; case DataBase.Types.Int64: fixed(void *numPtr = &mass[SPos]) { Values[k] = *(long *)numPtr; } SPos += sizeof(long); CheckRowDataLength += sizeof(long); CheckRowsDataLength += sizeof(long); break; case DataBase.Types.Int32: fixed(void *numPtr = &mass[SPos]) { Values[k] = *(int *)numPtr; } SPos += sizeof(int); CheckRowDataLength += sizeof(int); CheckRowsDataLength += sizeof(int); break; case DataBase.Types.RIU32: fixed(void *numPtr = &mass[SPos]) { Values[k] = new RIU32(*(uint *)numPtr); } SPos += sizeof(uint); CheckRowDataLength += sizeof(uint); CheckRowsDataLength += sizeof(uint); break; case DataBase.Types.String: //тут надо бдительничать! int StrLength; fixed(void *numPtr = &mass[SPos]) { StrLength = *(int *)numPtr; } SPos += sizeof(int); CheckRowDataLength += sizeof(int); CheckRowsDataLength += sizeof(int); Values[k] = Encoding.GetString(mass, SPos, StrLength); SPos += StrLength; CheckRowDataLength += StrLength; CheckRowsDataLength += StrLength; break; default: throw new Exception("не поддерживаемый тип"); } ColumnIndex++; } } if (CheckRowDataLength != RowDataLength) { throw new Exception($"Сообщение повреждено: {tables[i].STable.Name} {(j + 1).ToString()}-{ID} CheckRowDataLength != RowDataLength({CheckRowDataLength}!={RowDataLength})"); } } tables[i] = new Table() { STable = Table, Rows = rows }; if (CheckRowsDataLength != RowsDataLength) { throw new Exception($"Сообщение повреждено: {tables[i].STable.Name} CheckRowsDataLength != RowsDataLength({CheckRowsDataLength}!={RowsDataLength})"); } } return(new DeserializeResult() { Tables = tables, SynchDate = synchDT, UserID = userID }); }
private object ParseField(DataBase.IColumn column, string txt) { object result = null; switch (column.TypeCol) { case DataBase.Types.Bool: result = bool.Parse(txt); break; case DataBase.Types.AutoStatus: { bool boolResult; if (bool.TryParse(txt, out boolResult)) { result = (boolResult ? DataBase.AutoStatus.Used : DataBase.AutoStatus.UnUse); } else { result = Enum.Parse(typeof(DataBase.AutoStatus), txt, true); } } break; case DataBase.Types.Byte: result = byte.Parse(txt); break; case DataBase.Types.DateTime: result = DateTime.ParseExact(txt, "dd-MM-yyyy HH.mm.ss.fffffff", CultureInfo.InvariantCulture); break; case DataBase.Types.Double: { var str = ReplaceBackward(txt); result = Double.Parse(str); } break; case DataBase.Types.Decimal: { var str = ReplaceBackward(txt); result = Decimal.Parse(str); } break; case DataBase.Types.Int64: result = Int64.Parse(txt); break; case DataBase.Types.Int32: result = Int32.Parse(txt); break; case DataBase.Types.RIU32: result = new RIU32(UInt32.Parse(txt)); break; case DataBase.Types.String: result = ReplaceBackward(txt); break; default: throw new Exception("не поддерживаемый тип"); } return(result); }