Initial support for provider-defined functions from providers schema -json (#119)

* Initial support for provider-defined functions from providers schema -json

Reference: https://github.com/hashicorp/terraform-json/issues/118
Reference: https://github.com/hashicorp/terraform/pull/34450

The Terraform `providers schema -json` output implementation currently uses the entire `metadata functions -json` implementation, so has the additional nesting layer containing `format_version` and `function_signatures`.

* Remove extraneous function metadata object
diff --git a/metadata.go b/metadata.go
index eb52577..8ac111a 100644
--- a/metadata.go
+++ b/metadata.go
@@ -77,6 +77,14 @@
 	// of the function
 	Description string `json:"description,omitempty"`
 
+	// Summary is an optional shortened description of the function
+	Summary string `json:"summary,omitempty"`
+
+	// DeprecationMessage is an optional message that indicates that the
+	// function should be considered deprecated and what actions should be
+	// performed by the practitioner to handle the deprecation.
+	DeprecationMessage string `json:"deprecation_message,omitempty"`
+
 	// ReturnType is the ctyjson representation of the function's
 	// return types based on supplying all parameters using
 	// dynamic types. Functions can have dynamic return types.
diff --git a/schemas.go b/schemas.go
index 64f87d8..a2918ef 100644
--- a/schemas.go
+++ b/schemas.go
@@ -86,6 +86,9 @@
 
 	// The schemas for any data sources in this provider.
 	DataSourceSchemas map[string]*Schema `json:"data_source_schemas,omitempty"`
+
+	// The definitions for any functions in this provider.
+	Functions map[string]*FunctionSignature `json:"functions,omitempty"`
 }
 
 // Schema is the JSON representation of a particular schema
diff --git a/schemas_test.go b/schemas_test.go
index 5044559..53cbce2 100644
--- a/schemas_test.go
+++ b/schemas_test.go
@@ -26,6 +26,23 @@
 	}
 }
 
+func TestProviderSchemasValidate_functions(t *testing.T) {
+	f, err := os.Open("testdata/functions/schemas.json")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer f.Close()
+
+	var schemas *ProviderSchemas
+	if err := json.NewDecoder(f).Decode(&schemas); err != nil {
+		t.Fatal(err)
+	}
+
+	if err := schemas.Validate(); err != nil {
+		t.Fatal(err)
+	}
+}
+
 func TestProviderSchemasValidate_nestedAttributes(t *testing.T) {
 	f, err := os.Open("testdata/nested_attributes/schemas.json")
 	if err != nil {
diff --git a/testdata/functions/schemas.json b/testdata/functions/schemas.json
new file mode 100644
index 0000000..1d616b7
--- /dev/null
+++ b/testdata/functions/schemas.json
@@ -0,0 +1 @@
+{"format_version":"1.0","provider_schemas":{"example":{"provider":{"version":0,"block":{"attributes":{"example":{"type":"string","description_kind":"plain","optional":true}},"description_kind":"plain"}},"resource_schemas":{"framework_example":{"version":0,"block":{"attributes":{"id":{"type":"string","description":"Example identifier","description_kind":"markdown","computed":true}},"description":"Example resource","description_kind":"markdown"}}},"data_source_schemas":{"framework_example":{"version":0,"block":{"attributes":{"id":{"type":"string","description":"Example identifier","description_kind":"markdown","computed":true}},"description":"Example data source","description_kind":"markdown"}}},"functions":{"example":{"description":"Echoes given argument as result","summary":"Example function","return_type":"string","parameters":[{"name":"input","description":"String to echo","type":"string"}]}}}}}