eliminate @trusted hack in dyaml.emitter (#199)
eliminate @trusted hack in dyaml.emitter merged-on-behalf-of: BBasile <BBasile@users.noreply.github.com>
This commit is contained in:
parent
0a4057472a
commit
9c2ae02792
|
@ -87,11 +87,14 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
///Stream to write to.
|
///Stream to write to.
|
||||||
Range stream_;
|
Range stream_;
|
||||||
|
|
||||||
|
/// Type used for upcoming emitter steps
|
||||||
|
alias EmitterFunction = void function(typeof(this)*) @safe;
|
||||||
|
|
||||||
///Stack of states.
|
///Stack of states.
|
||||||
Appender!(void function() @safe[]) states_;
|
Appender!(EmitterFunction[]) states_;
|
||||||
|
|
||||||
///Current state.
|
///Current state.
|
||||||
//WARNING! DO NOT CALL DIRECTLY! Use callNext() instead!
|
EmitterFunction state_;
|
||||||
void function() @safe state_;
|
|
||||||
|
|
||||||
///Event queue.
|
///Event queue.
|
||||||
Queue!Event events_;
|
Queue!Event events_;
|
||||||
|
@ -172,13 +175,13 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
* lineBreak = Line break character/s.
|
* lineBreak = Line break character/s.
|
||||||
*/
|
*/
|
||||||
this(Range stream, const bool canonical, const int indent, const int width,
|
this(Range stream, const bool canonical, const int indent, const int width,
|
||||||
const LineBreak lineBreak) @trusted
|
const LineBreak lineBreak) @safe
|
||||||
{
|
{
|
||||||
states_.reserve(32);
|
states_.reserve(32);
|
||||||
indents_.reserve(32);
|
indents_.reserve(32);
|
||||||
stream_ = stream;
|
stream_ = stream;
|
||||||
canonical_ = canonical;
|
canonical_ = canonical;
|
||||||
nextExpected(&expectStreamStart);
|
nextExpected!"expectStreamStart"();
|
||||||
|
|
||||||
if(indent > 1 && indent < 10){bestIndent_ = indent;}
|
if(indent > 1 && indent < 10){bestIndent_ = indent;}
|
||||||
if(width > bestIndent_ * 2) {bestWidth_ = width;}
|
if(width > bestIndent_ * 2) {bestWidth_ = width;}
|
||||||
|
@ -201,7 +204,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///Pop and return the newest state in states_.
|
///Pop and return the newest state in states_.
|
||||||
void function() @safe popState() @safe
|
EmitterFunction popState() @safe
|
||||||
{
|
{
|
||||||
enforce(states_.data.length > 0,
|
enforce(states_.data.length > 0,
|
||||||
new YAMLException("Emitter: Need to pop a state but there are no states left"));
|
new YAMLException("Emitter: Need to pop a state but there are no states left"));
|
||||||
|
@ -210,9 +213,9 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pushState(void delegate() @safe func) @trusted
|
void pushState(string D)() @safe
|
||||||
{
|
{
|
||||||
states_ ~= func.funcptr;
|
states_ ~= mixin("function(typeof(this)* self) { self."~D~"(); }");
|
||||||
}
|
}
|
||||||
|
|
||||||
///Pop and return the newest indent in indents_.
|
///Pop and return the newest indent in indents_.
|
||||||
|
@ -328,7 +331,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
new EmitterException("Expected streamStart, but got " ~ event_.idString));
|
new EmitterException("Expected streamStart, but got " ~ event_.idString));
|
||||||
|
|
||||||
writeStreamStart();
|
writeStreamStart();
|
||||||
nextExpected(&expectDocumentStart!(Yes.first));
|
nextExpected!"expectDocumentStart!(Yes.first)"();
|
||||||
}
|
}
|
||||||
|
|
||||||
///Expect nothing, throwing if we still have something.
|
///Expect nothing, throwing if we still have something.
|
||||||
|
@ -392,7 +395,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
writeIndicator("---", Yes.needWhitespace);
|
writeIndicator("---", Yes.needWhitespace);
|
||||||
if(canonical_){writeIndent();}
|
if(canonical_){writeIndent();}
|
||||||
}
|
}
|
||||||
nextExpected(&expectRootNode);
|
nextExpected!"expectRootNode"();
|
||||||
}
|
}
|
||||||
else if(event_.id == EventID.streamEnd)
|
else if(event_.id == EventID.streamEnd)
|
||||||
{
|
{
|
||||||
|
@ -402,7 +405,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
writeIndent();
|
writeIndent();
|
||||||
}
|
}
|
||||||
writeStreamEnd();
|
writeStreamEnd();
|
||||||
nextExpected(&expectNothing);
|
nextExpected!"expectNothing"();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,13 +421,13 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
writeIndicator("...", Yes.needWhitespace);
|
writeIndicator("...", Yes.needWhitespace);
|
||||||
writeIndent();
|
writeIndent();
|
||||||
}
|
}
|
||||||
nextExpected(&expectDocumentStart!(No.first));
|
nextExpected!"expectDocumentStart!(No.first)"();
|
||||||
}
|
}
|
||||||
|
|
||||||
///Handle the root node of a document.
|
///Handle the root node of a document.
|
||||||
void expectRootNode() @safe
|
void expectRootNode() @safe
|
||||||
{
|
{
|
||||||
pushState(&expectDocumentEnd);
|
pushState!"expectDocumentEnd"();
|
||||||
expectNode(Context.root);
|
expectNode(Context.root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,7 +514,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
writeIndicator("[", Yes.needWhitespace, Yes.whitespace);
|
writeIndicator("[", Yes.needWhitespace, Yes.whitespace);
|
||||||
++flowLevel_;
|
++flowLevel_;
|
||||||
increaseIndent(Yes.flow);
|
increaseIndent(Yes.flow);
|
||||||
nextExpected(&expectFlowSequenceItem!(Yes.first));
|
nextExpected!"expectFlowSequenceItem!(Yes.first)"();
|
||||||
}
|
}
|
||||||
|
|
||||||
///Handle a flow sequence item.
|
///Handle a flow sequence item.
|
||||||
|
@ -532,7 +535,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
}
|
}
|
||||||
static if(!first){writeIndicator(",", No.needWhitespace);}
|
static if(!first){writeIndicator(",", No.needWhitespace);}
|
||||||
if(canonical_ || column_ > bestWidth_){writeIndent();}
|
if(canonical_ || column_ > bestWidth_){writeIndent();}
|
||||||
pushState(&expectFlowSequenceItem!(No.first));
|
pushState!"expectFlowSequenceItem!(No.first)"();
|
||||||
expectSequenceNode();
|
expectSequenceNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,7 +547,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
writeIndicator("{", Yes.needWhitespace, Yes.whitespace);
|
writeIndicator("{", Yes.needWhitespace, Yes.whitespace);
|
||||||
++flowLevel_;
|
++flowLevel_;
|
||||||
increaseIndent(Yes.flow);
|
increaseIndent(Yes.flow);
|
||||||
nextExpected(&expectFlowMappingKey!(Yes.first));
|
nextExpected!"expectFlowMappingKey!(Yes.first)"();
|
||||||
}
|
}
|
||||||
|
|
||||||
///Handle a key in a flow mapping.
|
///Handle a key in a flow mapping.
|
||||||
|
@ -568,13 +571,13 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
if(canonical_ || column_ > bestWidth_){writeIndent();}
|
if(canonical_ || column_ > bestWidth_){writeIndent();}
|
||||||
if(!canonical_ && checkSimpleKey())
|
if(!canonical_ && checkSimpleKey())
|
||||||
{
|
{
|
||||||
pushState(&expectFlowMappingSimpleValue);
|
pushState!"expectFlowMappingSimpleValue"();
|
||||||
expectMappingNode(true);
|
expectMappingNode(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeIndicator("?", Yes.needWhitespace);
|
writeIndicator("?", Yes.needWhitespace);
|
||||||
pushState(&expectFlowMappingValue);
|
pushState!"expectFlowMappingValue"();
|
||||||
expectMappingNode();
|
expectMappingNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,7 +585,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
void expectFlowMappingSimpleValue() @safe
|
void expectFlowMappingSimpleValue() @safe
|
||||||
{
|
{
|
||||||
writeIndicator(":", No.needWhitespace);
|
writeIndicator(":", No.needWhitespace);
|
||||||
pushState(&expectFlowMappingKey!(No.first));
|
pushState!"expectFlowMappingKey!(No.first)"();
|
||||||
expectMappingNode();
|
expectMappingNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,7 +594,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
{
|
{
|
||||||
if(canonical_ || column_ > bestWidth_){writeIndent();}
|
if(canonical_ || column_ > bestWidth_){writeIndent();}
|
||||||
writeIndicator(":", Yes.needWhitespace);
|
writeIndicator(":", Yes.needWhitespace);
|
||||||
pushState(&expectFlowMappingKey!(No.first));
|
pushState!"expectFlowMappingKey!(No.first)"();
|
||||||
expectMappingNode();
|
expectMappingNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,7 +606,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
const indentless = (context_ == Context.mappingNoSimpleKey ||
|
const indentless = (context_ == Context.mappingNoSimpleKey ||
|
||||||
context_ == Context.mappingSimpleKey) && !indentation_;
|
context_ == Context.mappingSimpleKey) && !indentation_;
|
||||||
increaseIndent(No.flow, indentless);
|
increaseIndent(No.flow, indentless);
|
||||||
nextExpected(&expectBlockSequenceItem!(Yes.first));
|
nextExpected!"expectBlockSequenceItem!(Yes.first)"();
|
||||||
}
|
}
|
||||||
|
|
||||||
///Handle a block sequence item.
|
///Handle a block sequence item.
|
||||||
|
@ -618,7 +621,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
|
|
||||||
writeIndent();
|
writeIndent();
|
||||||
writeIndicator("-", Yes.needWhitespace, No.whitespace, Yes.indentation);
|
writeIndicator("-", Yes.needWhitespace, No.whitespace, Yes.indentation);
|
||||||
pushState(&expectBlockSequenceItem!(No.first));
|
pushState!"expectBlockSequenceItem!(No.first)"();
|
||||||
expectSequenceNode();
|
expectSequenceNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,7 +631,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
void expectBlockMapping() @safe
|
void expectBlockMapping() @safe
|
||||||
{
|
{
|
||||||
increaseIndent(No.flow);
|
increaseIndent(No.flow);
|
||||||
nextExpected(&expectBlockMappingKey!(Yes.first));
|
nextExpected!"expectBlockMappingKey!(Yes.first)"();
|
||||||
}
|
}
|
||||||
|
|
||||||
///Handle a key in a block mapping.
|
///Handle a key in a block mapping.
|
||||||
|
@ -644,13 +647,13 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
writeIndent();
|
writeIndent();
|
||||||
if(checkSimpleKey())
|
if(checkSimpleKey())
|
||||||
{
|
{
|
||||||
pushState(&expectBlockMappingSimpleValue);
|
pushState!"expectBlockMappingSimpleValue"();
|
||||||
expectMappingNode(true);
|
expectMappingNode(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeIndicator("?", Yes.needWhitespace, No.whitespace, Yes.indentation);
|
writeIndicator("?", Yes.needWhitespace, No.whitespace, Yes.indentation);
|
||||||
pushState(&expectBlockMappingValue);
|
pushState!"expectBlockMappingValue"();
|
||||||
expectMappingNode();
|
expectMappingNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,7 +661,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
void expectBlockMappingSimpleValue() @safe
|
void expectBlockMappingSimpleValue() @safe
|
||||||
{
|
{
|
||||||
writeIndicator(":", No.needWhitespace);
|
writeIndicator(":", No.needWhitespace);
|
||||||
pushState(&expectBlockMappingKey!(No.first));
|
pushState!"expectBlockMappingKey!(No.first)"();
|
||||||
expectMappingNode();
|
expectMappingNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,7 +670,7 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
{
|
{
|
||||||
writeIndent();
|
writeIndent();
|
||||||
writeIndicator(":", Yes.needWhitespace, No.whitespace, Yes.indentation);
|
writeIndicator(":", Yes.needWhitespace, No.whitespace, Yes.indentation);
|
||||||
pushState(&expectBlockMappingKey!(No.first));
|
pushState!"expectBlockMappingKey!(No.first)"();
|
||||||
expectMappingNode();
|
expectMappingNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1294,21 +1297,17 @@ struct Emitter(Range, CharType) if (isOutputRange!(Range, CharType))
|
||||||
writeString(prefix);
|
writeString(prefix);
|
||||||
writeLineBreak();
|
writeLineBreak();
|
||||||
}
|
}
|
||||||
|
void nextExpected(string D)() @safe
|
||||||
void nextExpected(void delegate() @safe func) @trusted
|
|
||||||
{
|
{
|
||||||
state_ = func.funcptr;
|
state_ = mixin("function(typeof(this)* self) { self."~D~"(); }");
|
||||||
}
|
}
|
||||||
void nextExpected(void function() @safe func) @safe
|
void nextExpected(EmitterFunction f) @safe
|
||||||
{
|
{
|
||||||
state_ = func;
|
state_ = f;
|
||||||
}
|
}
|
||||||
void callNext() @trusted
|
void callNext() @safe
|
||||||
{
|
{
|
||||||
void delegate() @safe func;
|
state_(&this);
|
||||||
func.funcptr = state_;
|
|
||||||
func.ptr = &this;
|
|
||||||
func();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue