| 
					
				 | 
			
			
				@@ -33,6 +33,8 @@ package com.google.protobuf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.google.protobuf.nano.CodedInputByteBufferNano; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.google.protobuf.nano.EnumClassNanoMultiple; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.google.protobuf.nano.EnumClassNanos; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.google.protobuf.nano.EnumValidity; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.google.protobuf.nano.EnumValidityAccessors; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.google.protobuf.nano.Extensions; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.google.protobuf.nano.Extensions.AnotherMessage; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.google.protobuf.nano.Extensions.MessageWithGroup; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2092,6 +2094,126 @@ public class NanoTest extends TestCase { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assertEquals(nestedMsg2.bb, newMsg.repeatedNestedMessage[2].bb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * Tests that invalid enum values from the wire are not accepted. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  public void testNanoEnumValidity() throws Exception { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    final int invalid = 120; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    final int alsoInvalid = 121; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    EnumValidity.M m = new EnumValidity.M(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Sanity check & baseline of the assertions for the first case below. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(EnumValidity.E.default_, m.optionalE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(EnumValidity.E.BAZ, m.defaultE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    m.optionalE = invalid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    m.defaultE = invalid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // E contains all valid values 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    m.repeatedE = new int[] {EnumValidity.E.FOO, EnumValidity.E.BAR}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    m.packedE = new int[] {EnumValidity.E.FOO, EnumValidity.E.BAZ}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // E2 contains some invalid values 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    m.repeatedE2 = new int[] {invalid, EnumValidity.E.BAR, alsoInvalid}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    m.packedE2 = new int[] {EnumValidity.E.FOO, invalid, alsoInvalid}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // E3 contains all invalid values 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    m.repeatedE3 = new int[] {invalid, invalid}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    m.packedE3 = new int[] {alsoInvalid, alsoInvalid}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    byte[] serialized = MessageNano.toByteArray(m); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Sanity check that we do have all data in the byte array. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(31, serialized.length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Test 1: tests that invalid values aren't included in the deserialized message. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    EnumValidity.M deserialized = MessageNano.mergeFrom(new EnumValidity.M(), serialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(EnumValidity.E.default_, deserialized.optionalE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(EnumValidity.E.BAZ, deserialized.defaultE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertTrue(Arrays.equals( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        new int[] {EnumValidity.E.FOO, EnumValidity.E.BAR}, deserialized.repeatedE)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertTrue(Arrays.equals( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        new int[] {EnumValidity.E.FOO, EnumValidity.E.BAZ}, deserialized.packedE)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertTrue(Arrays.equals( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        new int[] {EnumValidity.E.BAR}, deserialized.repeatedE2)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertTrue(Arrays.equals( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        new int[] {EnumValidity.E.FOO}, deserialized.packedE2)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(0, deserialized.repeatedE3.length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(0, deserialized.packedE3.length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Test 2: tests that invalid values do not override previous values in the field, including 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // arrays, including pre-existing invalid values. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    deserialized.optionalE = EnumValidity.E.BAR; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    deserialized.defaultE = alsoInvalid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    deserialized.repeatedE = new int[] {EnumValidity.E.BAZ}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    deserialized.packedE = new int[] {EnumValidity.E.BAZ, alsoInvalid}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    deserialized.repeatedE2 = new int[] {invalid, alsoInvalid}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    deserialized.packedE2 = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    deserialized.repeatedE3 = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    deserialized.packedE3 = new int[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    MessageNano.mergeFrom(deserialized, serialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(EnumValidity.E.BAR, deserialized.optionalE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(alsoInvalid, deserialized.defaultE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertTrue(Arrays.equals( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        new int[] {EnumValidity.E.BAZ, /* + */ EnumValidity.E.FOO, EnumValidity.E.BAR}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        deserialized.repeatedE)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertTrue(Arrays.equals( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        new int[] {EnumValidity.E.BAZ, alsoInvalid, /* + */ EnumValidity.E.FOO, EnumValidity.E.BAZ}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        deserialized.packedE)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertTrue(Arrays.equals( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        new int[] {invalid, alsoInvalid, /* + */ EnumValidity.E.BAR}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        deserialized.repeatedE2)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertTrue(Arrays.equals( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        new int[] {/* <null> + */ EnumValidity.E.FOO}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        deserialized.packedE2)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertNull(deserialized.repeatedE3); // null + all invalid == null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(0, deserialized.packedE3.length); // empty + all invalid == empty 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Test 3: reading by alternative forms 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    EnumValidity.Alt alt = MessageNano.mergeFrom(new EnumValidity.Alt(), serialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(EnumValidity.E.BAR, // last valid value in m.repeatedE2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        alt.repeatedE2AsOptional); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertTrue(Arrays.equals(new int[] {EnumValidity.E.FOO}, alt.packedE2AsNonPacked)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(0, alt.nonPackedE3AsPacked.length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * Tests the same as {@link #testNanoEnumValidity()} with accessor style. Repeated fields are 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * not re-tested here because they are not affected by the accessor style. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  public void testNanoEnumValidityAccessors() throws Exception { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    final int invalid = 120; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    final int alsoInvalid = 121; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    EnumValidityAccessors.M m = new EnumValidityAccessors.M(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Sanity check & baseline of the assertions for the first case below. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(EnumValidityAccessors.default_, m.getOptionalE()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(EnumValidityAccessors.BAZ, m.getDefaultE()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    m.setOptionalE(invalid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    m.setDefaultE(invalid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Set repeatedE2 for Alt.repeatedE2AsOptional 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    m.repeatedE2 = new int[] {invalid, EnumValidityAccessors.BAR, alsoInvalid}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    byte[] serialized = MessageNano.toByteArray(m); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Sanity check that we do have all data in the byte array. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(10, serialized.length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Test 1: tests that invalid values aren't included in the deserialized message. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    EnumValidityAccessors.M deserialized = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        MessageNano.mergeFrom(new EnumValidityAccessors.M(), serialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(EnumValidityAccessors.default_, deserialized.getOptionalE()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(EnumValidityAccessors.BAZ, deserialized.getDefaultE()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Test 2: tests that invalid values do not override previous values in the field, including 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // pre-existing invalid values. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    deserialized.setOptionalE(EnumValidityAccessors.BAR); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    deserialized.setDefaultE(alsoInvalid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    MessageNano.mergeFrom(deserialized, serialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(EnumValidityAccessors.BAR, deserialized.getOptionalE()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(alsoInvalid, deserialized.getDefaultE()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Test 3: reading by alternative forms 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    EnumValidityAccessors.Alt alt = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        MessageNano.mergeFrom(new EnumValidityAccessors.Alt(), serialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertEquals(EnumValidityAccessors.BAR, // last valid value in m.repeatedE2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        alt.getRepeatedE2AsOptional()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    * Tests that code generation correctly wraps a single message into its outer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    * class. The class {@code SingleMessageNano} is imported from the outer 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3248,12 +3370,16 @@ public class NanoTest extends TestCase { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // Check that repeated fields with packable types can accept both packed and unpacked 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // serialized forms. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     NanoRepeatedPackables.NonPacked nonPacked = new NanoRepeatedPackables.NonPacked(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    nonPacked.int32S = new int[] {1, 2, 3}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    nonPacked.int64S = new long[] {4, 5, 6}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    nonPacked.uint32S = new int[] {7, 8, 9}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    nonPacked.uint64S = new long[] {10, 11, 12}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    nonPacked.sint32S = new int[] {13, 14, 15}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    nonPacked.sint64S = new long[] {16, 17, 18}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Exaggerates the first values of varint-typed arrays. This is to test that the parsing code 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // of packed fields handles non-packed data correctly. If the code incorrectly thinks it is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // reading from a packed tag, it will read the first value as the byte length of the field, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // and the large number will cause the input to go out of bounds, thus capturing the error. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    nonPacked.int32S = new int[] {1000, 2, 3}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    nonPacked.int64S = new long[] {4000, 5, 6}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    nonPacked.uint32S = new int[] {7000, 8, 9}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    nonPacked.uint64S = new long[] {10000, 11, 12}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    nonPacked.sint32S = new int[] {13000, 14, 15}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    nonPacked.sint64S = new long[] {16000, 17, 18}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     nonPacked.fixed32S = new int[] {19, 20, 21}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     nonPacked.fixed64S = new long[] {22, 23, 24}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     nonPacked.sfixed32S = new int[] {25, 26, 27}; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3290,8 +3416,8 @@ public class NanoTest extends TestCase { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     nonPacked = MessageNano.mergeFrom(new NanoRepeatedPackables.NonPacked(), mixedSerialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     packed = MessageNano.mergeFrom(new NanoRepeatedPackables.Packed(), mixedSerialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assertRepeatedPackablesEqual(nonPacked, packed); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    assertTrue(Arrays.equals(new int[] {1, 2, 3, 1, 2, 3}, nonPacked.int32S)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    assertTrue(Arrays.equals(new int[] {13, 14, 15, 13, 14, 15}, nonPacked.sint32S)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertTrue(Arrays.equals(new int[] {1000, 2, 3, 1000, 2, 3}, nonPacked.int32S)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assertTrue(Arrays.equals(new int[] {13000, 14, 15, 13000, 14, 15}, nonPacked.sint32S)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assertTrue(Arrays.equals(new int[] {25, 26, 27, 25, 26, 27}, nonPacked.sfixed32S)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assertTrue(Arrays.equals(new boolean[] {false, true, false, true}, nonPacked.bools)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 |