Index: lucene/core/src/test/org/apache/lucene/index/TestCustomNorms.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/index/TestCustomNorms.java	(revision 1405946)
+++ lucene/core/src/test/org/apache/lucene/index/TestCustomNorms.java	(working copy)
@@ -22,6 +22,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.DocValues.Source;
 import org.apache.lucene.index.DocValues.Type;
@@ -33,6 +34,7 @@
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.LineFileDocs;
 import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util._TestUtil;
 
 /**
  * 
@@ -82,6 +84,39 @@
     dir.close();
     docs.close();
   }
+  
+  public void testPackedNorms() throws IOException {
+    Directory dir = newDirectory();
+    IndexWriterConfig config = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random()));
+    config.setSimilarity(new PackedNormSimilarity());
+    RandomIndexWriter writer = new RandomIndexWriter(random(), dir, config);
+    int num = _TestUtil.nextInt(random(), 1, 1000);
+    for (int i = 0; i < num; i++) {
+      Document doc = new Document();
+      doc.add(new StringField("len", Integer.toString(i), Field.Store.YES));
+      StringBuilder sb = new StringBuilder();
+      for (int j = 0; j < i; j++) {
+        sb.append(" token");
+      }
+      doc.add(new TextField("content", sb.toString(), Field.Store.NO));
+      writer.addDocument(doc);
+    }
+    
+    DirectoryReader ir = writer.getReader();
+    writer.close();
+    for (AtomicReaderContext context : ir.leaves()) {
+      AtomicReader reader = context.reader();
+      DocValues norms = reader.normValues("content");
+      assertNotNull(norms);
+      Source source = norms.getSource();
+      assertEquals(Type.VAR_INTS, source.getType());
+      for (int i = 0; i < reader.maxDoc(); i++) {
+        assertEquals(source.getInt(i), Long.parseLong(reader.document(i).get("len")));
+      }
+    }
+    ir.close();
+    dir.close();
+  }
 
   public void testExceptionOnRandomType() throws IOException {
     Directory dir = newDirectory();
@@ -200,6 +235,13 @@
       norm.setFloat(boost);
     }
   }
+  
+  public static class PackedNormSimilarity extends DefaultSimilarity {
+    @Override
+    public void computeNorm(FieldInvertState state, Norm norm) {
+      norm.setPackedLong(state.getLength());
+    }
+  }
 
   public static class RandomTypeSimilarity extends DefaultSimilarity {
 
Index: lucene/core/src/java/org/apache/lucene/index/Norm.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/index/Norm.java	(revision 1405946)
+++ lucene/core/src/java/org/apache/lucene/index/Norm.java	(working copy)
@@ -115,6 +115,15 @@
     setType(Type.FIXED_INTS_64);
     this.field.setLongValue(norm);
   }
+  
+  /**
+   * Sets a packed long norm value.
+   * @lucene.experimental
+   */
+  public void setPackedLong(long norm) {
+    setType(Type.VAR_INTS);
+    this.field.setLongValue(norm);
+  }
 
   /**
    * Sets a byte norm value
