code: func SerializeResourceForHash(buf *bytes.Buffer, val interface{}, resource *Resource) {
  	if val == nil {
  		return
  	}
  	sm := resource.Schema
  	m := val.(map[string]interface{})
  	var keys []string
  	for k := range sm {
  		keys = append(keys, k)
  	}
  	sort.Strings(keys)
  	for _, k := range keys {
  		innerSchema := sm[k]
  		// Skip attributes that are not user-provided. Computed attributes
  		// do not contribute to the hash since their ultimate value cannot
  		// be known at plan/diff time.
  		if !(innerSchema.Required || innerSchema.Optional) {
  			continue
  		}
  
  		buf.WriteString(k)
  		buf.WriteRune(':')
  		innerVal := m[k]
  		SerializeValueForHash(buf, innerVal, innerSchema)
  	}
  }
docs: // SerializeValueForHash appends a serialization of the given resource config
  // to the given buffer, guaranteeing deterministic results given the same value
  // and schema.
  //
  // Its primary purpose is as input into a hashing function in order
  // to hash complex substructures when used in sets, and so the serialization
  // is not reversible.