private void PushPendingCharactersToValue() { if (Partial.CurrentColumnIndex >= Columns.Length) { Throw.InvalidOperationException($"Unexpected column (Index={Partial.CurrentColumnIndex})"); } var dataSpan = Partial.PendingAsMemory(Buffer.Buffer); var colIx = Partial.CurrentColumnIndex; var column = Columns[colIx]; if (column.IsRequired && dataSpan.Length == 0) { Throw.SerializationException($"Column [{column.Name}] is required, but was not found in row"); } var ctx = new ReadContext(RowNumber, colIx, Columns[colIx].Name, Context); if (!column.Set(dataSpan.Span, in ctx, Partial.Value)) { Throw.InvalidOperationException($"Could not assign value \"{Partial.PendingAsString(Buffer.Buffer)}\" to column \"{column.Name}\" (Index={Partial.CurrentColumnIndex})"); } Partial.ClearBufferAndAdvanceColumnIndex(); }
internal ReaderStateMachine( MemoryPool <char> memoryPool, char escapeStartChar, char valueSeparatorChar, char escapeChar, RowEndings rowEndings, ReadHeaders hasHeaders, char?commentChar ) { RowEndings = rowEndings; HasHeaders = hasHeaders; switch (HasHeaders) { case ReadHeaders.Always: CurrentState = State.Header_Start; break; case ReadHeaders.Never: CurrentState = State.Record_Start; break; default: Throw.InvalidOperationException($"Unexpected {nameof(ReadHeaders)}: {HasHeaders}"); break; } TransitionMatrixHandle = GetTransitionMatrix(RowEndings, escapeStartChar == escapeChar).Pin(); TransitionMatrix = (TransitionRule *)TransitionMatrixHandle.Pointer; SuppressCharLookupDispose = false; (MinimumCharacter, CharLookupOffset, CharLookupOwner, CharLookupPin, CharLookup) = MakeCharacterLookup(memoryPool, escapeStartChar, valueSeparatorChar, escapeChar, commentChar); }
private void AssertCanMakeReader() { if (!RowBuilder.HasValue) { Throw.InvalidOperationException($"Cannot make a reader for {typeof(T).Name}, returned {nameof(InstanceProvider)} and {nameof(DeserializableMember)}s were not sufficient."); } }
private void AssertCanMakeWriter() { if (SerializeColumns.Length == 0) { Throw.InvalidOperationException($"No columns configured to write for {typeof(T).FullName}"); } }
internal ReaderStateMachine( CharacterLookup preAllocLookup, char escapeStartChar, char escapeChar, RowEndings rowEndings, ReadHeaders hasHeaders ) { RowEndings = rowEndings; HasHeaders = hasHeaders; switch (HasHeaders) { case ReadHeaders.Always: CurrentState = State.Header_Start; break; case ReadHeaders.Never: CurrentState = State.Record_Start; break; default: Throw.InvalidOperationException($"Unexpected {nameof(ReadHeaders)}: {HasHeaders}"); break; } TransitionMatrixHandle = GetTransitionMatrix(RowEndings, escapeStartChar == escapeChar).Pin(); TransitionMatrix = (TransitionRule *)TransitionMatrixHandle.Pointer; SuppressCharLookupDispose = true; (MinimumCharacter, CharLookupOffset, _, _, CharLookup) = preAllocLookup; }
/// <summary> /// Create a new IBoundConfiguration(T) with the given Options, for /// use with the given type. /// </summary> public static IBoundConfiguration <TRow> For <TRow>(Options options) { Utils.CheckArgumentNull(options, nameof(options)); var forType = typeof(TRow).GetTypeInfo(); if (forType == Types.Object) { Throw.InvalidOperationException($"Use {nameof(ForDynamic)} when creating configurations for dynamic types"); } var deserializeMembers = options.TypeDescriber.EnumerateMembersToDeserialize(forType); var serializeMembers = options.TypeDescriber.EnumerateMembersToSerialize(forType); var provider = options.TypeDescriber.GetInstanceProvider(forType); ValidateTypeDescription(forType, deserializeMembers, serializeMembers, provider); var serializeColumns = CreateSerializeColumns(forType, options, serializeMembers); char?escapeStartEnd = options.EscapedValueStartAndEnd; var valueSep = options.ValueSeparator; // this is entirely knowable now, so go ahead and calculate // and save for future use var needsEscape = DetermineNeedsEscape(serializeColumns, escapeStartEnd, valueSep); return (new ConcreteBoundConfiguration <TRow>( provider, deserializeMembers, serializeColumns, needsEscape, options )); }
private void AddToPushback(ReadOnlySpan <char> c) { if (!PushBackOwner.HasValue) { PushBackOwner.Value = MemoryPool.Rent(BufferSizeHint); } var pushBackOwnerValue = PushBackOwner.Value; if (PushBackLength + c.Length > pushBackOwnerValue.Memory.Length) { var oldSize = pushBackOwnerValue.Memory.Length; var newSize = (PushBackLength + c.Length) * 2; // double size, because we're sharing the buffer var newOwner = Utils.RentMustIncrease(MemoryPool, newSize, oldSize); pushBackOwnerValue.Memory.CopyTo(newOwner.Memory); pushBackOwnerValue.Dispose(); PushBackOwner.Value = pushBackOwnerValue = newOwner; } if (PushBackLength + c.Length > pushBackOwnerValue.Memory.Length) { Throw.InvalidOperationException($"Could not allocate large enough buffer to read headers"); } c.CopyTo(PushBack.Span.Slice(PushBackLength)); PushBackLength += c.Length; }
protected internal ReadWithCommentResult <T> HandleAdvanceResult(ReadWithCommentResultType res, bool returnComments, bool ending) { switch (res) { case ReadWithCommentResultType.HasComment: if (returnComments) { var comment = Partial.PendingAsString(Buffer.Buffer); Partial.ClearBuffer(); return(new ReadWithCommentResult <T>(comment)); } Partial.ClearBuffer(); return(ReadWithCommentResult <T> .Empty); case ReadWithCommentResultType.HasValue: var record = GetValueForReturn(); return(new ReadWithCommentResult <T>(record)); case ReadWithCommentResultType.NoValue: if (ending) { EndedWithoutReturningRow(); } return(ReadWithCommentResult <T> .Empty); default: Throw.InvalidOperationException($"Unexpected {nameof(ReadWithCommentResultType)}: {res}"); return(default); } }
private static SerializableMember Map(TypeInfo ontoType, SerializableMember member) { ShouldSerialize?shouldSerializeOnType; if (member.ShouldSerialize.HasValue) { var surrogateShouldSerializeWrapper = member.ShouldSerialize.Value; if (surrogateShouldSerializeWrapper.Mode == BackingMode.Method) { if (surrogateShouldSerializeWrapper.Takes.HasValue && surrogateShouldSerializeWrapper.IsStatic) { Throw.InvalidOperationException($"Cannot map 'should serialize' {surrogateShouldSerializeWrapper} onto {ontoType}, it takes a parameter"); } var surrogateShouldSerialize = surrogateShouldSerializeWrapper.Method.Value; var surrogateShouldSerializeBinding = GetEquivalentFlagsFor(surrogateShouldSerialize.IsPublic, surrogateShouldSerialize.IsStatic); // intentionally letting this be null var shouldSerializeOnTypeMtd = ontoType.GetMethod(surrogateShouldSerialize.Name, surrogateShouldSerializeBinding); if (shouldSerializeOnTypeMtd == null) { Throw.InvalidOperationException($"No equivalent to {surrogateShouldSerialize} found on {ontoType}"); } shouldSerializeOnType = ShouldSerialize.ForMethod(shouldSerializeOnTypeMtd); } else { Throw.InvalidOperationException($"Cannot map 'should serialize' {surrogateShouldSerializeWrapper} onto {ontoType}, 'should serialize' isn't backed by a method"); return(default);
// internal for testing purposes internal ManualTypeDescriberBuilder WithSerializableMember(TypeInfo?forType, Getter?getter, string?name, Formatter?formatter, ShouldSerialize?shouldSerialize, EmitDefaultValue emitDefault) { if (forType == null) { Throw.ArgumentNullException(nameof(forType)); } if (getter == null) { Throw.ArgumentNullException(nameof(getter)); } if (name == null) { Throw.ArgumentNullException(nameof(name)); } if (formatter == null) { Throw.ArgumentNullException(nameof(name)); } // shouldSerialize can be null if (getter.RowType.HasValue) { var getterOnType = getter.RowType.Value; var isLegal = false; TypeInfo?cur = forType; while (cur != null) { if (cur == getterOnType) { isLegal = true; break; } cur = cur?.BaseType?.GetTypeInfo(); } if (!isLegal) { Throw.InvalidOperationException($"Provided getter ({getter}) is not on {forType} or one of it's base types."); } } var toAdd = SerializableMember.Create(forType, name, getter, formatter, shouldSerialize, emitDefault); if (!Serializers.TryGetValue(forType, out var s)) { Serializers[forType] = s = ImmutableArray.CreateBuilder <SerializableMember>(); } s.Add(toAdd); return(this); }
internal static object GetValueNonNull(this PropertyInfo prop, object?obj) { var ret = prop.GetValue(obj); if (ret == null) { Throw.InvalidOperationException($"Expected non-null value when reading property {prop}, but was null"); } return(ret); }
internal ReadOnlySpan <char> GetDataSpan() { var row = SafeRowGet(); if (!row.TryGetDataSpan(ColumnNumber, out var ret)) { Throw.InvalidOperationException($"{nameof(DynamicCell)} unexpectedly backed by null span"); } return(ret); }
public bool TryRead(out T record) { AssertNotDisposed(); if (!Configuration.NewCons(out record)) { Throw.InvalidOperationException($"Failed to construct new instance of {typeof(T)}"); } return(TryReadWithReuse(ref record)); }
internal static object GetValueNonNull(this FieldInfo field, object?obj) { var ret = field.GetValue(obj); if (ret == null) { Throw.InvalidOperationException($"Expected non-null value when reading field {field}, but was null"); } return(ret); }
public bool TryReadWithReuse(ref T record) { AssertNotDisposed(); if (RowEndings == null) { HandleLineEndings(); } if (ReadHeaders == null) { HandleHeaders(); } while (true) { PreparingToWriteToBuffer(); var available = Buffer.Read(Inner); if (available == 0) { EndOfData(); if (HasValueToReturn) { record = GetValueForReturn(); return(true); } // intentionally _not_ modifying record here return(false); } if (!HasValueToReturn) { if (record == null) { if (!Configuration.NewCons(out record)) { Throw.InvalidOperationException($"Failed to construct new instance of {typeof(T)}"); } } SetValueToPopulate(record); } var res = AdvanceWork(available); if (res) { record = GetValueForReturn(); return(true); } } }
public InstanceProvider?GetInstanceProvider(TypeInfo forType) { if (!Builders.TryGetValue(forType, out var ret)) { if (ThrowsOnNoConfiguredType) { Throw.InvalidOperationException($"No configured instance provider for {forType}"); } return(Fallback.GetInstanceProvider(forType)); } return(ret); }
public override IAsyncWriter <T> CreateAsyncWriter(TextWriter inner, object context = null) { if (SerializeColumns.Length == 0) { Throw.InvalidOperationException($"No columns configured to write for {typeof(T).FullName}"); } if (inner == null) { Throw.ArgumentNullException(nameof(inner)); } return(new AsyncWriter <T>(this, inner, context)); }
internal static SerializableMember CreateInner(TypeInfo?beingSerializedType, string?name, Getter?getter, Formatter?formatter, ShouldSerialize?shouldSerialize, EmitDefaultValue emitDefault) { if (beingSerializedType == null) { Throw.ArgumentNullException(nameof(beingSerializedType)); } if (name == null) { Throw.ArgumentNullException(nameof(name)); } if (getter == null) { Throw.ArgumentNullException(nameof(getter)); } if (formatter == null) { Throw.ArgumentNullException(nameof(formatter)); } bool emitDefaultValueBool; switch (emitDefault) { case Cesil.EmitDefaultValue.Yes: emitDefaultValueBool = true; break; case Cesil.EmitDefaultValue.No: emitDefaultValueBool = false; break; default: Throw.InvalidOperationException($"Unexpected {nameof(Cesil.EmitDefaultValue)}: {emitDefault}"); return(default); } var toSerializeType = getter.Returns; if (!formatter.Takes.IsAssignableFrom(toSerializeType)) { Throw.ArgumentException($"The first parameter to {nameof(formatter)} must accept a {toSerializeType}", nameof(formatter)); } CheckShouldSerializeMethod(shouldSerialize, getter.RowType); return(new SerializableMember(name, getter, formatter, shouldSerialize, emitDefaultValueBool)); }
// internal for testing purposes internal static NameLookup CreateInner(OrdererNames ordered, MemoryPool <char> memoryPool) { if (TryCreateAdaptiveRadixTrie(ordered, memoryPool, out var trieOwner, out var trieMem)) { return(new NameLookup(Algorithm.AdaptiveRadixTrie, trieOwner, trieMem)); } if (TryCreateBinarySearch(ordered, memoryPool, out var binaryTreeOwner, out var binaryTreeMem)) { return(new NameLookup(Algorithm.BinarySearch, binaryTreeOwner, binaryTreeMem)); } Throw.InvalidOperationException($"Could create a lookup for dynamic member names, names could not fit in memory acquired from MemoryPool: {memoryPool}"); return(default);
/// <summary> /// Enumerate all the members on forType to deserialize. /// /// If no members has been registered, will either delegate to a fallback /// ITypeProvider or throw an exception depending on configuration. /// </summary> public IEnumerable <DeserializableMember> EnumerateMembersToDeserialize(TypeInfo forType) { if (!Deserializers.TryGetValue(forType, out var ret)) { if (ThrowsOnNoConfiguredType) { Throw.InvalidOperationException($"No configured members to deserialize for {forType}"); } return(Fallback.EnumerateMembersToDeserialize(forType)); } return(ret); }
public override IReader <T> CreateReader(TextReader inner, object context = null) { if (DeserializeColumns.Length == 0) { Throw.InvalidOperationException($"No columns configured to read for {typeof(T).FullName}"); } if (inner == null) { Throw.ArgumentNullException(nameof(inner)); } return(new Reader <T>(inner, this, context)); }
internal void Init(IDynamicRowOwner owner, int rowNumber, int width, IDynamicTypeConverter converter, string[] names, MemoryPool <char> pool) { if (!IsDisposed) { Throw.InvalidOperationException("DynamicRow not in an uninitializable state"); } Owner = owner; RowNumber = rowNumber; Converter = converter; MemoryPool = pool; Width = width; Names = names; Generation++; }
/// <summary> /// Gets an instance builder usable to construct the given type. /// /// If a surrogate is registered, the surrogate will be used for discovery - the returned /// constructor will be mapped from the surrogate to forType. /// /// If a surrogate is not registered, either an exception will be thrown or forType will /// be passed to TypeDescriber.GetInstanceBuilder depending on the value of /// ThrowOnNoRegisteredSurrogate. /// </summary> public InstanceBuilder GetInstanceBuilder(TypeInfo forType) { if (!SurrogateTypes.TryGetValue(forType, out var proxy)) { if (ThrowOnNoRegisteredSurrogate) { Throw.InvalidOperationException($"No surrogate registered for {forType}"); } return(TypeDescriber.GetInstanceBuilder(forType)); } var fromProxy = TypeDescriber.GetInstanceBuilder(forType); return(Map(forType, fromProxy)); }
internal void GetDataSpanAndReadContext(out ReadOnlySpan <char> data, out ReadContext ctx) { var r = SafeRowGet(); if (!r.TryGetDataSpan(ColumnNumber, out data)) { data = default; ctx = default; Throw.InvalidOperationException($"{nameof(DynamicCell)} unexpectedly backed by null span"); } var name = r.Columns[ColumnNumber]; var owner = r.Owner; ctx = ReadContext.ReadingColumn(owner.Options, r.RowNumber, name, owner.Context); }
internal unsafe void Initialize( CharacterLookup preAllocLookup, char?escapeStartChar, char?escapeChar, ReadRowEnding rowEndings, ReadHeader hasHeaders, bool readingComments, bool skipLeadingWhitespace, bool skipTrailingWhitespace ) { CharacterLookup = preAllocLookup; CharLookup = (CharacterType *)preAllocLookup.Memory; RowEndings = rowEndings; HasHeaders = hasHeaders; switch (HasHeaders) { case ReadHeader.Always: CurrentState = State.Header_Start; break; case ReadHeader.Never: CurrentState = State.Record_Start; break; default: Throw.InvalidOperationException($"Unexpected {nameof(ReadHeader)}: {HasHeaders}"); break; } TransitionMatrix = GetTransitionMatrix( RowEndings, escapeStartChar.HasValue && escapeStartChar == escapeChar, readingComments, skipLeadingWhitespace, skipTrailingWhitespace, #if DEBUG out TransitionMatrixMemoryOffset #else out _ #endif ); }
public override void WriteComment(ReadOnlySpan <char> comment) { AssertNotDisposed(this); AssertNotPoisoned(Configuration); try { WriteHeadersAndEndRowIfNeeded(); var options = Configuration.Options; var commentCharNullable = options.CommentCharacter; if (commentCharNullable == null) { Throw.InvalidOperationException($"No {nameof(Options.CommentCharacter)} configured, cannot write a comment line"); } var commentChar = commentCharNullable.Value; var rowEndingSpan = Configuration.RowEndingMemory.Span; var splitIx = Utils.FindNextIx(0, comment, rowEndingSpan); if (splitIx == -1) { // single segment PlaceCharInStaging(commentChar); if (comment.Length > 0) { PlaceAllInStaging(comment); } } else { // multi segment var prevIx = 0; var isFirstRow = true; while (splitIx != -1) { if (!isFirstRow) { EndRecord(); } PlaceCharInStaging(commentChar); var segSpan = comment[prevIx..splitIx];
/// <summary> /// Registered a surrogate type for forType. /// /// Whenever forType is passed to one of the EnumerateXXX methods, surrogateType /// will be used to discover members instead. The discovered members will then /// be mapped to forType, and returned. /// </summary> public SurrogateTypeDescriberBuilder WithSurrogateType(TypeInfo forType, TypeInfo surrogateType) { Utils.CheckArgumentNull(forType, nameof(forType)); Utils.CheckArgumentNull(surrogateType, nameof(surrogateType)); if (forType == surrogateType) { Throw.InvalidOperationException($"Type {forType} cannot be a surrogate for itself"); } if (SurrogateTypes.ContainsKey(forType)) { Throw.InvalidOperationException($"Surrogate already registered for {forType}"); } SurrogateTypes[forType] = surrogateType; return(this); }
private void HandleHeaders() { ReadHeaders = Configuration.ReadHeader; TryMakeStateMachine(); var allowColumnsByName = Configuration.ReadHeader == Cesil.ReadHeaders.Always; using (var reader = new HeadersReader <object>(Configuration, SharedCharacterLookup, Inner, Buffer)) { var res = reader.Read(); var foundHeaders = res.Headers.Count; if (foundHeaders == 0) { Throw.InvalidOperationException("Expected a header row, but found no headers"); } Columns = new Column[foundHeaders]; if (allowColumnsByName) { ColumnNames = new string[foundHeaders]; } using (var e = res.Headers) { var ix = 0; while (e.MoveNext()) { var name = allowColumnsByName ? new string(e.Current.Span) : null; if (name != null) { ColumnNames[ix] = name; } var col = new Column(name, Column.MakeDynamicSetter(name, ix), null, false); Columns[ix] = col; ix++; } } Buffer.PushBackFromOutsideBuffer(res.PushBack); } }
internal static IMemoryOwner <T> RentMustIncrease <T>(MemoryPool <T> pool, int newSize, int oldSize) { int requestSize; if (newSize > pool.MaxBufferSize) { if (oldSize >= pool.MaxBufferSize) { Throw.InvalidOperationException($"Needed a larger memory segment than could be requested, needed {newSize:N0}; {nameof(MemoryPool<T>.MaxBufferSize)} = {pool.MaxBufferSize:N0}"); } requestSize = pool.MaxBufferSize; } else { requestSize = newSize; } return(pool.Rent(requestSize)); }
internal void AssertNotPoisoned <T>(IBoundConfiguration <T> self) { if (Poison != null) { switch (Poison.Value) { case PoisonType.Cancelled: Throw.InvalidOperationException("Object is in an invalid state, a previous operation was canceled"); return; case PoisonType.Exception: Throw.InvalidOperationException("Object is in an invalid state, a previous operation raised an exception"); return; default: Throw.ImpossibleException($"Unexpected {nameof(PoisonType)}: {Poison}", self); return; } } }