[ 
https://issues.apache.org/jira/browse/AVRO-3001?focusedWorklogId=802321&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-802321
 ]

ASF GitHub Bot logged work on AVRO-3001:
----------------------------------------

                Author: ASF GitHub Bot
            Created on: 22/Aug/22 01:36
            Start Date: 22/Aug/22 01:36
    Worklog Time Spent: 10m 
      Work Description: github-code-scanning[bot] commented on code in PR #1833:
URL: https://github.com/apache/avro/pull/1833#discussion_r950941158


##########
lang/csharp/src/apache/main/IO/Parsing/ValidatingGrammarGenerator.cs:
##########
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+
+namespace Avro.IO.Parsing
+{
+    /// <summary>
+    /// The class that generates validating grammar.
+    /// </summary>
+    public class ValidatingGrammarGenerator
+    {
+        /// <summary>
+        /// Returns the non-terminal that is the start symbol for the grammar 
for the
+        /// given schema <tt>sc</tt>.
+        /// </summary>
+        public virtual Symbol Generate(Schema schema)
+        {
+            return Symbol.NewRoot(Generate(schema, new Dictionary<LitS, 
Symbol>()));
+        }
+
+        /// <summary>
+        /// Returns the non-terminal that is the start symbol for the grammar 
for the
+        /// given schema <tt>sc</tt>. If there is already an entry for the 
given schema
+        /// in the given map <tt>seen</tt> then that entry is returned. 
Otherwise a new
+        /// symbol is generated and an entry is inserted into the map.
+        /// </summary>
+        /// <param name="sc">   The schema for which the start symbol is 
required </param>
+        /// <param name="seen"> A map of schema to symbol mapping done so far. 
</param>
+        /// <returns> The start symbol for the schema </returns>
+        protected virtual Symbol Generate(Schema sc, IDictionary<LitS, Symbol> 
seen)
+        {
+            switch (sc.Tag)
+            {
+                case Schema.Type.Null:
+                    return Symbol.Null;
+                case Schema.Type.Boolean:
+                    return Symbol.Boolean;
+                case Schema.Type.Int:
+                    return Symbol.Int;
+                case Schema.Type.Long:
+                    return Symbol.Long;
+                case Schema.Type.Float:
+                    return Symbol.Float;
+                case Schema.Type.Double:
+                    return Symbol.Double;
+                case Schema.Type.String:
+                    return Symbol.String;
+                case Schema.Type.Bytes:
+                    return Symbol.Bytes;
+                case Schema.Type.Fixed:
+                    return Symbol.NewSeq(new 
Symbol.IntCheckAction(((FixedSchema)sc).Size), Symbol.Fixed);
+                case Schema.Type.Enumeration:
+                    return Symbol.NewSeq(new 
Symbol.IntCheckAction(((EnumSchema)sc).Symbols.Count), Symbol.Enum);
+                case Schema.Type.Array:
+                    return Symbol.NewSeq(
+                        Symbol.NewRepeat(Symbol.ArrayEnd, 
Generate(((ArraySchema)sc).ItemSchema, seen)),
+                        Symbol.ArrayStart);
+                case Schema.Type.Map:
+                    return Symbol.NewSeq(
+                        Symbol.NewRepeat(Symbol.MapEnd, 
Generate(((MapSchema)sc).ValueSchema, seen), Symbol.String),
+                        Symbol.MapStart);
+                case Schema.Type.Record:
+                    {
+                        LitS wsc = new LitS(sc);
+                        Symbol rresult = seen.ContainsKey(wsc) ? seen[wsc] : 
null;
+                        if (rresult == null)
+                        {
+                            Symbol[] production = new 
Symbol[((RecordSchema)sc).Fields.Count];
+
+                            // We construct a symbol without filling the 
array. Please see
+                            // <seealso cref="Symbol.production"/> for the 
reason.
+                            rresult = Symbol.NewSeq(production);
+                            seen[wsc] = rresult;
+
+                            int j = production.Length;
+                            foreach (Field f in ((RecordSchema)sc).Fields)
+                            {
+                                production[--j] = Generate(f.Schema, seen);
+                            }
+                        }
+
+                        return rresult;
+                    }
+                case Schema.Type.Union:
+                    IList<Schema> subs = ((UnionSchema)sc).Schemas;
+                    Symbol[] symbols = new Symbol[subs.Count];
+                    string[] labels = new string[subs.Count];
+
+                    int i = 0;
+                    foreach (Schema b in ((UnionSchema)sc).Schemas)
+                    {
+                        symbols[i] = Generate(b, seen);
+                        labels[i] = b.Fullname;
+                        i++;
+                    }
+
+                    return Symbol.NewSeq(Symbol.NewAlt(symbols, labels), 
Symbol.Union);
+
+                default:
+                    throw new Exception("Unexpected schema type");
+            }
+        }
+
+        /// <summary>
+        /// A wrapper around Schema that does "==" equality.
+        /// </summary>
+        protected class LitS
+        {
+            private readonly Schema actual;
+
+            /// <summary>
+            /// Initializes a new instance of the <see cref="LitS"/> class.
+            /// </summary>
+            public LitS(Schema actual)
+            {
+                this.actual = actual;
+            }
+
+            /// <summary>
+            /// Two LitS are equal if and only if their underlying schema is 
the same (not
+            /// merely equal).
+            /// </summary>
+            public override bool Equals(object o)
+            {
+                if (!(o is LitS))

Review Comment:
   ## Equals should not apply "is"
   
   LitS.Equals(object) should not use "is" on its parameter, as it will not 
work properly for subclasses of LitS.
   
   [Show more 
details](https://github.com/apache/avro/security/code-scanning/2904)



##########
lang/csharp/src/apache/main/IO/Parsing/Symbol.cs:
##########
@@ -0,0 +1,1044 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Avro.IO.Parsing
+{
+    /// <summary>
+    /// Symbol is the base of all symbols (terminals and non-terminals) of the
+    /// grammar.
+    /// </summary>
+    public abstract class Symbol
+    {
+        /// <summary>
+        /// The type of symbol.
+        /// </summary>
+        public enum Kind
+        {
+            /// <summary>
+            /// terminal symbols which have no productions </summary>
+            Terminal,
+
+            /// <summary>
+            /// Start symbol for some grammar </summary>
+            Root,
+
+            /// <summary>
+            /// non-terminal symbol which is a sequence of one or more other 
symbols </summary>
+            Sequence,
+
+            /// <summary>
+            /// non-terminal to represent the contents of an array or map 
</summary>
+            Repeater,
+
+            /// <summary>
+            /// non-terminal to represent the union </summary>
+            Alternative,
+
+            /// <summary>
+            /// non-terminal action symbol which are automatically consumed 
</summary>
+            ImplicitAction,
+
+            /// <summary>
+            /// non-terminal action symbol which is explicitly consumed 
</summary>
+            ExplicitAction
+        }
+
+        /// The kind of this symbol.
+        public readonly Kind SymKind;
+
+        /// <summary>
+        /// The production for this symbol. If this symbol is a terminal this 
is
+        /// <tt>null</tt>. Otherwise this holds the the sequence of the 
symbols that
+        /// forms the production for this symbol. The sequence is in the 
reverse order of
+        /// production. This is useful for easy copying onto parsing stack.
+        ///
+        /// Please note that this is a final. So the production for a symbol 
should be
+        /// known before that symbol is constructed. This requirement cannot 
be met for
+        /// those symbols which are recursive (e.g. a record that holds union 
a branch of
+        /// which is the record itself). To resolve this problem, we 
initialize the
+        /// symbol with an array of nulls. Later we fill the symbols. Not 
clean, but
+        /// works. The other option is to not have this field a final. But 
keeping it
+        /// final and thus keeping symbol immutable gives some comfort. See 
various
+        /// generators how we generate records.
+        /// </summary>
+        public readonly Symbol[] Production;
+
+        /// <summary>
+        /// Constructs a new symbol of the given kind.
+        /// </summary>
+        protected Symbol(Kind kind) : this(kind, null)
+        {
+        }
+
+        /// <summary>
+        /// Constructs a new symbol of the given kind and production.
+        /// </summary>
+        protected Symbol(Kind kind, Symbol[] production)
+        {
+            this.Production = production;
+            this.SymKind = kind;
+        }
+
+        /// <summary>
+        /// A convenience method to construct a root symbol.
+        /// </summary>
+        public static Symbol NewRoot(params Symbol[] symbols)
+        {
+            return new Root(symbols);
+        }
+
+        /// <summary>
+        /// A convenience method to construct a sequence.
+        /// </summary>
+        /// <param name="production"> The constituent symbols of the sequence. 
</param>
+        public static Symbol NewSeq(params Symbol[] production)
+        {
+            return new Sequence(production);
+        }
+
+        /// <summary>
+        /// A convenience method to construct a repeater.
+        /// </summary>
+        /// <param name="endSymbol"> The end symbol. </param>
+        /// <param name="symsToRepeat"> The symbols to repeat in the repeater. 
</param>
+        public static Symbol NewRepeat(Symbol endSymbol, params Symbol[] 
symsToRepeat)
+        {
+            return new Repeater(endSymbol, symsToRepeat);
+        }
+
+        /// <summary>
+        /// A convenience method to construct a union.
+        /// </summary>
+        public static Symbol NewAlt(Symbol[] symbols, string[] labels)
+        {
+            return new Alternative(symbols, labels);
+        }
+
+        /// <summary>
+        /// A convenience method to construct an ErrorAction.
+        /// </summary>
+        /// <param name="e"> </param>
+        protected static Symbol Error(string e)
+        {
+            return new ErrorAction(e);
+        }
+
+        /// <summary>
+        /// A convenience method to construct a ResolvingAction.
+        /// </summary>
+        /// <param name="w"> The writer symbol </param>
+        /// <param name="r"> The reader symbol </param>
+        protected static Symbol Resolve(Symbol w, Symbol r)
+        {
+            return new ResolvingAction(w, r);
+        }
+
+        /// <summary>
+        /// Fixup symbol.
+        /// </summary>
+        protected class Fixup
+        {
+            /// <summary>
+            /// The symbols.
+            /// </summary>
+            public readonly Symbol[] Symbols;
+            /// <summary>
+            /// The position.
+            /// </summary>
+            public readonly int Pos;
+
+            /// <summary>
+            /// Initializes a new instance of the <see cref="Fixup"/> class.
+            /// </summary>
+            public Fixup(Symbol[] symbols, int pos)

Review Comment:
   ## Exposing internal representation
   
   'Fixup' exposes the internal representation stored in field 'Symbols'. The 
value may be modified [through the variable out](1).
   'Fixup' exposes the internal representation stored in field 'Symbols'. The 
value may be modified [through the variable out](2).
   'Fixup' exposes the internal representation stored in field 'Symbols'. The 
value may be modified [through the variable out](3).
   'Fixup' exposes the internal representation stored in field 'Symbols'. The 
value may be modified [through the variable out](4).
   
   [Show more 
details](https://github.com/apache/avro/security/code-scanning/2903)





Issue Time Tracking
-------------------

    Worklog Id:     (was: 802321)
    Time Spent: 0.5h  (was: 20m)

> JsconEncode Decode support for C#
> ---------------------------------
>
>                 Key: AVRO-3001
>                 URL: https://issues.apache.org/jira/browse/AVRO-3001
>             Project: Apache Avro
>          Issue Type: Improvement
>          Components: csharp
>    Affects Versions: 1.10.0, 1.11.0
>            Reporter: Krishnan Unni
>            Priority: Major
>              Labels: pull-request-available
>          Time Spent: 0.5h
>  Remaining Estimate: 0h
>
> The C# library for avro currently supports only the Binary encoding and also 
> with compile time types (Generic support only). As part of a project I am 
> doing I need to validate the avro schema against the incoming json data on 
> the fly without a predefined type (generated class). So basically comparing 
> an avro schema (string/json representation) against a raw json string. It is 
> possible with the Java library since it supports both non generic types and 
> streams as well as json encoding. With C# currently this is not possible. Is 
> there a plan to extend the C# library to provide these features? If yes, is 
> there a timeline? If not is there any alternative to achieve this? 



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to